--- /dev/null
+
+CFILES += siska_vfs.c
+CFILES += siska_fs0.c
+CFILES += siska_printf.c
+CFILES += siska_fops_memory_dev.c
+
+all:
+ gcc -g -O3 $(CFILES)
--- /dev/null
+
+BOOT_SEG = 0x07c0
+
+INIT_SEG = 0x9000
+INIT_OFFSET = 0x0200
+INIT_SECTIONS = 1
+INIT_SECTION_START = 1
+
+SYS_SEG = 0x1000
+SYS_SECTIONS = 137 + 1 + 20
+SYS_SECTION_START = 2
+
+.code16
+.text
+.global _start
+
+.align 4
+_start:
+ ljmp $BOOT_SEG, $_start2
+
+_start2:
+ movw %cs, %ax
+ movw %ax, %ds
+
+ movw $INIT_SEG, %ax
+ movw %ax, %es
+
+ xorw %si, %si
+ xorw %di, %di
+ movw $0x100, %cx
+ rep movsw
+
+ ljmp $INIT_SEG, $_read
+_read:
+ movw %cs, %ax
+ movw %ax, %ds
+ movw %ax, %es
+ movw %ax, %ss
+ movw $0x1000, %sp
+
+#read init code
+ movw $INIT_OFFSET, %bx
+ movw $INIT_SECTION_START, %cx
+ movw $INIT_SECTIONS, %dx
+ call _read_floppy
+
+#read sys code
+ movw $SYS_SEG, %ax
+ xorw %bx, %bx
+ movw $SYS_SECTION_START, %cx
+ movw $SYS_SECTIONS, %dx
+ call _read_floppy
+
+ ljmp $INIT_SEG, $INIT_OFFSET
+
+_read_error:
+ movw $_msg_err, %ax
+ movw $8, %cx
+ call _print
+1:
+ jmp 1b
+
+.align 4
+_nb_sections:
+ .word 0
+_cylind:
+ .byte 0
+_section:
+ .byte 0
+_head:
+ .byte 0
+.align 4
+_read_floppy:
+#BIOS int 13H
+#ah = 02H
+#al = section count
+#ch = cylind number
+#cl = section number start
+#dh = head number
+#dl = driver number
+#es:bx = buffer
+#return value: cf = 0 ok, ah = 0, al = section count
+#return value: cf != 0 error, ah = error number
+
+#input args:
+#ax, buffer seg
+#bx, buffer offset
+#cx, start section
+#dx, total sections
+
+ cmpw $1024, %dx
+ jl 1f
+
+ movw $_msg_kernel_too_big, %ax
+ movw $14, %cx
+ call _print
+_too_big:
+ jmp _too_big
+
+1:
+ movw %dx, _nb_sections
+ movw %ax, %es
+
+#floppy 80 cylinds, 2 head, 18 sections, we count section No. from 0
+#get start cylind, head, section.
+ movw %cx, %ax
+ movb $36, %cl
+ divb %cl
+ movb %al, _cylind
+
+ shrw $8, %ax
+ movb $18, %cl
+ divb %cl
+ movb %al, _head
+ movb %ah, _section
+
+_rep_read:
+ movb _section, %cl
+ movb $18, %al
+ subb %cl, %al
+ addb $1, %cl
+ xorb %ah, %ah
+
+ cmpw %ax, _nb_sections
+ jge 2f
+ movw _nb_sections, %ax
+2:
+ movw %bx, %dx
+ shrw $9, %dx
+ addw %ax, %dx
+ subw $128, %dx
+ jle 3f
+ subb %dl, %al
+3:
+ movb $0x2, %ah
+
+ movb _cylind, %ch
+ movb _head, %dh
+ movb $0, %dl
+ int $0x13
+ jc _read_error
+
+ movb $0, %ah
+ subw %ax, _nb_sections
+ je _read_ok
+
+ movw %ax, %dx
+ shlw $9, %dx
+
+ addb %al, _section
+ cmpb $18, _section
+ jl 4f
+
+ movb $0, _section
+ addb $1, _head
+ cmpb $2, _head
+ jl 4f
+
+ movb $0, _head
+ addb $1, _cylind
+4:
+ addw %dx, %bx
+ jnc _rep_read
+
+ movw %es, %ax
+ addw $0x1000, %ax
+ movw %ax, %es
+ xorw %bx, %bx
+ jmp _rep_read
+
+_read_ok:
+ movw $_msg_ok, %ax
+ movw $7, %cx
+ call _print
+ ret
+
+.align 4
+_print:
+#ah = 13h
+#al = show mode
+#bh = page No.
+#bl = priority
+#cx = string len
+#dh = row
+#dl = col
+#es:bp = string addr
+#int 10h
+
+ movw %ax, %bp
+ movw %cs, %ax
+ movw %ax, %es
+
+ movb $0x13, %ah
+ movb $0x0, %al
+ movb $0x0, %bh
+ movb $0x8f, %bl
+ movw $0x0, %dx
+ int $0x10
+ ret
+
+.align 4
+_msg_ok:
+.asciz "read ok"
+
+.align 4
+_msg_err:
+.asciz "read err"
+
+.align 4
+_msg_kernel_too_big:
+.asciz "kernel too big"
+
+.org 500
+_rootfs_data:
+.word 138, 0
+_rootfs_size:
+.word 20, 0
+.word 0
+
+.byte 0x55
+.byte 0xAA
--- /dev/null
+#!/bin/bash
+
+as boot.s --32 -o boot.o
+as init.s --32 -o init.o
+as head.s --32 -o head.o
+as siska_syscall.s --32 -o siska_syscall.o
+as siska_page.s --32 -o siska_page.o
+
+as execve.s --32 -o execve.o
+
+gcc -c -O3 -m32 main.c -fno-stack-protector
+gcc -c -O3 -m32 siska_mm.c -fno-stack-protector
+gcc -c -O3 -m32 siska_task.c -fno-stack-protector
+gcc -c -O3 -m32 siska_printf.c -fno-stack-protector
+gcc -c -O3 -m32 siska_console.c -fno-stack-protector
+gcc -c -O3 -m32 siska_vfs.c -fno-stack-protector
+gcc -c -O3 -m32 siska_fs0.c -fno-stack-protector
+gcc -c -O3 -m32 siska_api.c -fno-stack-protector
+gcc -c -O3 -m32 siska_fops_memory_dev.c -fno-stack-protector
+
+FILES="head.o \
+ main.o \
+ siska_syscall.o \
+ siska_task.o \
+ siska_printf.o \
+ siska_console.o \
+ siska_vfs.o \
+ siska_fs0.o \
+ siska_fops_memory_dev.o \
+ siska_mm.o \
+ siska_page.o \
+ siska_api.o"
+
+ld -static -melf_i386 -Ttext 0x00000000 $FILES -o siska
+
+objdump -d boot.o -M i8086 > boot.txt
+#objdump -d init.o -M i8086
+#objdump -d head.o -M i8086
+objdump -d siska -M i386 > siska.txt
+
+objdump -d execve.o -M i386 > execve.txt
+
+objcopy -S -O binary boot.o boot.bin
+objcopy -S -O binary init.o init.bin
+objcopy -S -O binary siska siska.bin
+objcopy -S -O binary execve.o execve.bin
+
+dd if=boot.bin of=~/3rdparty/bochs/a.img bs=512 count=1 conv=notrunc
+dd if=init.bin of=~/3rdparty/bochs/a.img bs=512 count=1 conv=notrunc seek=1
+dd if=siska.bin of=~/3rdparty/bochs/a.img bs=512 conv=notrunc seek=2
+dd if=fs.bin of=~/3rdparty/bochs/a.img bs=512 conv=notrunc seek=140
+
+rm *.o siska
+
--- /dev/null
+
+.code32
+.text
+.global _start
+
+.align 4
+_start:
+ jmp 2f
+1:
+ popl %ebx
+ movl $3, %eax
+ movl $9, %ecx
+ int $0x80
+
+ movl $6, %eax
+ int $0x80
+2:
+ call 1b
+_exec_msg:
+.asciz "exec ok!\n"
+
--- /dev/null
+
+.code32
+.text
+.global _start, _task0, _tss0, _idt
+.global siska_printk, _main
+
+.align 4
+_start:
+_pg_dir:
+
+ movl $0x10, %eax
+ mov %ax, %ds
+ mov %ax, %es
+ mov %ax, %fs
+ mov %ax, %gs
+ lss _init_stack, %esp
+
+ call _setup_idt
+ call _setup_gdt
+
+ movl $0x10, %eax
+ mov %ax, %ds
+ mov %ax, %es
+ mov %ax, %fs
+ mov %ax, %gs
+ lss _init_stack, %esp
+
+ xorl %eax, %eax
+1:
+ incl %eax
+ movl %eax, 0x000000
+ cmpl %eax, 0x100000
+ je 1b
+
+ movl %cr0, %eax
+ andl $0x80000011, %eax
+ orl $0x2, %eax
+ movl %eax, %cr0
+
+ call _check_x87
+ jmp _after_page_tables
+
+_check_x87:
+ fninit
+ fstsw %ax
+ cmpb $0, %al
+ je 1f
+
+ movl %cr0, %eax
+ xorl $0x6, %eax
+ movl %eax, %cr0
+ ret
+.align 4
+1:
+ .byte 0xdb, 0xe4
+ ret
+
+.align 4
+_setup_idt:
+ lea _ignore_int_handler, %edx
+
+ movl $0x00080000, %eax
+ movw %dx, %ax
+ movw $0x8e00, %dx
+
+ lea _idt, %edi
+ movl $256, %ecx
+1:
+ movl %eax, (%edi)
+ movl %edx, 4(%edi)
+ addl $8, %edi
+ decl %ecx
+ jne 1b
+
+ lidt _idt_desc
+ ret
+
+.align 4
+_setup_gdt:
+ lgdt _gdt_desc
+ ret
+
+.org 0x1000
+_pg_table0:
+
+.org 0x5000
+_task0:
+ .fill 4096, 1, 0
+_init_stack:
+ .long _init_stack
+ .word 0x10
+.align 4
+_tmp_floppy_area:
+ .fill 1024, 1, 0
+
+.align 4
+_after_page_tables:
+ pushl $0
+ pushl $0
+ pushl $0
+ pushl $_L6
+ pushl $_main
+
+ jmp _setup_pages
+_L6:
+ jmp _L6
+
+.align 4
+_setup_pages:
+ movl $1024 * 5, %ecx
+ xorl %eax, %eax
+ xorl %edi, %edi
+ cld
+ rep stosl
+
+ xorl %edi, %edi
+ movl $0x1007, (%edi)
+ movl $0x2007, 4(%edi)
+ movl $0x3007, 8(%edi)
+ movl $0x4007, 12(%edi)
+
+ movl $0x0007, %eax
+ movl $0x1000, %edi
+1:
+ movl %eax, (%edi)
+ addl $0x1000, %eax
+ addl $4, %edi
+ cmpl $0x1000007, %eax
+ jl 1b
+
+ xorl %eax, %eax
+ movl %eax, %cr3
+ movl %cr0, %eax
+ orl $0x80000000, %eax
+ movl %eax, %cr0
+ ret
+
+.align 4
+_init_msg:
+.asciz "unknown interrupt!\n"
+
+.align 4
+_ignore_int_handler:
+ pushl %eax
+ pushl %ecx
+ pushl %edx
+ push %ds
+ push %es
+ push %fs
+
+ movl $0x10, %eax
+ mov %ax, %ds
+ mov %ax, %es
+ mov %ax, %fs
+
+ pushl $_init_msg
+ call siska_printk
+ popl %eax
+
+ pop %fs
+ pop %es
+ pop %ds
+ popl %edx
+ popl %ecx
+ popl %eax
+ iret
+
+.align 4
+.word 0
+_idt_desc:
+ .word 256 * 8 - 1
+ .long _idt
+
+.align 4
+.word 0
+_gdt_desc:
+ .word 256 * 8 - 1
+ .long _gdt
+
+.align 4
+_idt:
+ .fill 256, 8, 0
+
+_gdt:
+ .word 0x0000, 0x0000, 0x0000, 0x0000 # 0 not use
+
+ .word 0xffff, 0x0000, 0x9a00, 0x00cf # 0x8 kernel code
+ .word 0xffff, 0x0000, 0x9200, 0x00cf # 0x10 kernel data
+
+ .word 0x0000, 0x0000, 0x0000, 0x0000 # 0x18 not use
+
+ .word 0x0068, _tss0, 0xe900, 0x0000 # 0x20 tss0
+ .word 0x0040, _ldt0, 0xe200, 0x0000 # 0x28 ldt0
+
+ .fill 250, 8, 0
+_ldt0:
+ .word 0x0000, 0x0000, 0x0000, 0x0000 # 0 not use
+ .word 0xffff, 0x0000, 0xfa00, 0x00cf # 0xf user code
+ .word 0xffff, 0x0000, 0xf200, 0x00cf # 0x17 user data
+_tss0:
+ .fill 104, 1, 0
+
--- /dev/null
+
+INIT_SEG = 0x9000
+INIT_OFFSET = 0x0200
+
+SYS_SEG = 0x1000
+
+DATA_OFFSET_VGA_CUR_COL = 0x0
+DATA_OFFSET_VGA_CUR_ROW = 0x1
+
+DATA_OFFSET_MEM_SIZE = 0x2
+
+DATA_OFFSET_VGA_CUR_PAGE = 0x5
+DATA_OFFSET_VGA_CUR_MODE = 0x6
+DATA_OFFSET_VGA_CUR_WIDTH = 0x7
+
+DATA_OFFSET_VGA_SIZE = 0xa
+DATA_OFFSET_VGA_MODE = 0xb
+DATA_OFFSET_VGA_PARAM = 0xc
+DATA_OFFSET_VGA_ROW = 0xe
+DATA_OFFSET_VGA_COL = 0xf
+
+.code16
+.text
+.global _start
+
+.align 4
+_start:
+
+#get extended memory size > 1M, based on KB
+ movb $0x88, %ah
+ int $0x15
+ movw %ax, (DATA_OFFSET_MEM_SIZE)
+
+#get VGA params
+ movb $0x12, %ah
+ movb $0x10, %bl
+ int $0x10
+ movb %bl, (DATA_OFFSET_VGA_SIZE)
+ movb %bh, (DATA_OFFSET_VGA_MODE)
+ movw %cx, (DATA_OFFSET_VGA_PARAM)
+ movw $0x5019, %ax
+ movb %al, (DATA_OFFSET_VGA_ROW)
+ movb %ah, (DATA_OFFSET_VGA_COL)
+
+ movb $0x03, %ah
+ xorb %bh, %bh
+ int $0x10
+ movb %dl, (DATA_OFFSET_VGA_CUR_COL)
+ movb %dh, (DATA_OFFSET_VGA_CUR_ROW)
+
+ movb $0x0f, %ah
+ int $0x10
+ movb %al, (DATA_OFFSET_VGA_CUR_MODE)
+ movb %ah, (DATA_OFFSET_VGA_CUR_WIDTH)
+ movb %bh, (DATA_OFFSET_VGA_CUR_PAGE)
+
+ cli
+ xorw %ax, %ax
+ cld
+_mov_sys:
+ movw %ax, %es
+
+ addw $SYS_SEG, %ax
+ cmpw $INIT_SEG, %ax
+ jz _end_mov_sys
+
+ movw %ax, %ds
+ xorw %si, %si
+ xorw %di, %di
+ movw $0x8000, %cx
+ rep movsw
+ jmp _mov_sys
+
+_end_mov_sys:
+
+ movw $INIT_SEG, %ax
+ movw %ax, %ds
+
+#load global description table & interrupt description table
+ lidt _idt_48 + INIT_OFFSET
+ lgdt _gdt_48 + INIT_OFFSET
+
+#enable A20
+ call _empty_8042
+
+ movb $0xd1, %al
+ out %al, $0x64
+ call _empty_8042
+
+ movb $0xdf, %al
+ out %al, $0x60
+ call _empty_8042
+
+#set 8259 interrupt chips, 0x20-0x21 for master, 0xa0-0xa1 for slave
+
+#start programming
+ movb $0x11, %al
+ out %al, $0x20
+ .word 0x00eb, 0x00eb
+ out %al, $0xa0
+ .word 0x00eb, 0x00eb
+
+#interrupt NO. from 0x20 in master
+ movb $0x20, %al
+ out %al, $0x21
+ .word 0x00eb, 0x00eb
+
+#interrupt NO. from 0x28 in slave
+ movb $0x28, %al
+ out %al, $0xa1
+ .word 0x00eb, 0x00eb
+
+#master irq 2 connect to slave
+ movb $0x04, %al
+ out %al, $0x21
+ .word 0x00eb, 0x00eb
+
+#slave connect to master's irq 2
+ movb $0x02, %al
+ out %al, $0xa1
+ .word 0x00eb, 0x00eb
+
+ movb $0x01, %al
+ out %al, $0x21
+ .word 0x00eb, 0x00eb
+ out %al, $0xa1
+ .word 0x00eb, 0x00eb
+
+#disable all interrupts of master and slave
+ movb $0xff, %al
+ out %al, $0x21
+ .word 0x00eb, 0x00eb
+ out %al, $0xa1
+ .word 0x00eb, 0x00eb
+
+ movw $0x1, %ax
+ lmsw %ax
+ ljmp $8, $0
+
+1:
+ jmp 1b
+
+.align 4
+_empty_8042:
+ .word 0x00eb, 0x00eb
+ in $0x64, %al
+ test $0x2, %al
+ jnz _empty_8042
+ ret
+
+.align 16
+_gdt:
+ .word 0, 0, 0, 0
+
+ .word 0x07ff
+ .word 0x0000
+ .word 0x9a00
+ .word 0x00c0
+
+ .word 0x07ff
+ .word 0x0000
+ .word 0x9200
+ .word 0x00c0
+
+.align 16
+_idt_48:
+ .word 0, 0, 0
+
+.align 16
+_gdt_48:
+ .word 0x800
+ .word INIT_OFFSET + _gdt
+ .word 0x9
+
+.align 4
+_print:
+#ah = 13h
+#al = show mode
+#bh = page No.
+#bl = priority
+#cx = string len
+#dh = row
+#dl = col
+#es:bp = string addr
+#int 10h
+
+ movw %ax, %bp
+ movw %cs, %ax
+ movw %ax, %es
+
+ movb $0x13, %ah
+ movb $0x0, %al
+ movb $0x0, %bh
+ movb $0x8f, %bl
+ movw $0x0, %dx
+ int $0x10
+ ret
+
+.align 4
+_init_msg:
+.asciz "init ok"
--- /dev/null
+
+#include"siska_task.h"
+#include"siska_mm.h"
+#include"siska_vfs.h"
+#include"siska_api.h"
+
+void siska_console_init();
+
+int siska_write(siska_regs_t* regs)
+{
+ const char* fmt = (const char*)regs->ebx;
+
+ return siska_console_write(fmt);
+}
+
+int _do_timer()
+{
+ siska_schedule();
+ return 0;
+}
+
+int _do_syscall_default()
+{
+ siska_printk("syscall default!\n");
+ return 0;
+}
+
+void _syscall_init()
+{
+ int i;
+ for (i = 0; i < 256; i++)
+ set_syscall_handler(i, _do_syscall_default);
+
+ set_syscall_handler(SISKA_SYSCALL_FORK, siska_fork);
+ set_syscall_handler(SISKA_SYSCALL_SCHED, siska_schedule);
+
+ set_syscall_handler(SISKA_SYSCALL_WRITE, siska_write);
+
+ set_syscall_handler(SISKA_SYSCALL_KILL, siska_kill);
+ set_syscall_handler(SISKA_SYSCALL_SIGNAL, siska_signal);
+
+ set_syscall_handler(SISKA_SYSCALL_EXIT, siska_exit);
+ set_syscall_handler(SISKA_SYSCALL_WAIT, siska_wait);
+
+ set_syscall_handler(SISKA_SYSCALL_GETPID, siska_getpid);
+ set_syscall_handler(SISKA_SYSCALL_GETPPID, siska_getppid);
+
+ set_syscall_handler(SISKA_SYSCALL_EXECVE, siska_execve);
+}
+
+int _main()
+{
+ siska_tss_t* tss0 = get_asm_addr(_tss0);
+ siska_task_t* task0 = get_asm_addr(_task0);
+
+ set_intr_handler(SISKA_INTERRUPT_PAGE_FAULT, _page_fault_int_handler);
+
+ _jiffies = 0;
+
+#define HZ 100u
+#define LATCH (1193180u / HZ)
+#if 1
+ outb_p(0x36, 0x43);
+ outb_p(LATCH & 0xff, 0x40);
+ outb(LATCH >> 8, 0x40);
+ set_intr_handler(SISKA_INTERRUPT_TIMER, _timer_int_handler);
+ outb(inb_p(0x21) & ~0x01, 0x21);
+#endif
+ set_trap_handler(SISKA_INTERRUPT_SYSCALL, _syscall_handler);
+
+ siska_console_init();
+
+ _syscall_init();
+
+ siska_task_init();
+ siska_mm_init();
+ siska_fs_init();
+
+#if 0
+ siska_file_t* file = NULL;
+
+ int ret = siska_vfs_open(&file, "/home/execve",
+ SISKA_FILE_FILE | SISKA_FILE_FLAG_R | SISKA_FILE_FLAG_W,
+ 0777);
+ siska_printk("open /home/execve, ret: %d\n", ret);
+ if (ret < 0) {
+ return -1;
+ }
+#if 1
+ char buf[64];
+ ret = siska_vfs_read(file, buf, sizeof(buf) - 1);
+ if (ret < 0) {
+ siska_printk("read /home/execve error, ret: %d\n", ret);
+ return -1;
+ }
+ siska_printk("/home/execve, ret: %d, buf: %s\n", ret, buf);
+#endif
+#endif
+
+ tss0->esp0 = (unsigned long)task0 + PG_SIZE;
+ tss0->ss0 = 0x10;
+ tss0->cs = 0xf;
+ tss0->ds = 0x17;
+ tss0->es = 0x17;
+ tss0->fs = 0x17;
+ tss0->gs = 0x17;
+ tss0->ldt = 0x28;
+ tss0->iomap = 0x80000000;
+
+ task0->pid = 0;
+ task0->ppid = -1;
+ task0->cr3 = 0;
+
+ task0->code3 = (unsigned long)task0 + sizeof(siska_task_t);
+ task0->data3 = (unsigned long)task0 + sizeof(siska_task_t);
+ task0->heap3 = (unsigned long)task0 + sizeof(siska_task_t);
+ task0->brk3 = (unsigned long)task0 + sizeof(siska_task_t);
+ task0->ebp3 = (unsigned long)task0 + PG_SIZE;
+ task0->end3 = (unsigned long)task0 + PG_SIZE;
+
+ task0->signal_flags = 0;
+ siska_memset(task0->signal_handlers, (unsigned long)SISKA_SIG_DFL, SISKA_NB_SIGNALS * sizeof(void*));
+
+ asm volatile(
+ "pushfl\n\t"
+ "andl $0xffffbfff, (%%esp)\n\t"
+ "popfl\n\t"
+ "movl $0x20, %%eax\n\t"
+ "ltr %%ax\n\t"
+ "movl $0x28, %%eax\n\t"
+ "lldt %%ax\n\t"
+ "sti\n\t"
+ :
+ :
+ :"eax"
+ );
+
+ asm volatile(
+ "movl %%esp, %%eax\n\t"
+ "pushl $0x17\n\t"
+ "pushl %%eax\n\t"
+ "pushfl\n\t"
+ "pushl $0xf\n\t"
+ "pushl $1f\n\t"
+ "iret\n\t"
+ "1:\n\t"
+ "movl $0x17, %%eax\n\t"
+ "movl %%eax, %%ds\n\t"
+ "movl %%eax, %%es\n\t"
+ "movl %%eax, %%fs\n\t"
+ "movl %%eax, %%gs\n\t"
+ :
+ :
+ :"eax"
+ );
+#if 1
+ int cpid = siska_api_syscall(SISKA_SYSCALL_FORK, 0, 0, 0);
+ if (-1 == cpid) {
+ while (1) {
+ }
+ } else if (0 == cpid) {
+ siska_api_execve(get_asm_addr(_execve_msg), 0, 0);
+ while (1) {
+
+// siska_api_syscall(SISKA_SYSCALL_KILL, 0, SISKA_SIGINT, 0);
+// siska_api_printf(get_asm_addr(_fork1_msg));
+// volatile unsigned long* p = (volatile unsigned long*)(1u << 30);
+// *p = 0x1234;
+// siska_api_syscall(SISKA_SYSCALL_SCHED, 0, 0, 0);
+ }
+ } else {
+ while (1) {
+// siska_api_printf(get_asm_addr(_fork0_msg));
+
+// siska_api_syscall(SISKA_SYSCALL_KILL, 1, SISKA_SIGINT, 0);
+ }
+ }
+#endif
+ return 0;
+}
+
--- /dev/null
+
+#include"siska_api.h"
+
+int siska_api_printf(const char* fmt, ...)
+{
+ char buf[128];
+
+ siska_va_list ap;
+
+ siska_va_start(ap, fmt);
+ int n = siska_vsnprintf(buf, sizeof(buf), fmt, ap);
+ siska_va_end(ap);
+
+ if (n > 0)
+ return siska_api_syscall(SISKA_SYSCALL_WRITE, (unsigned long)buf, n, 0);
+ return n;
+}
+
+int siska_api_execve(const char* filename, char* const argv, char* const envp)
+{
+ return siska_api_syscall(SISKA_SYSCALL_EXECVE, (unsigned long)filename, (unsigned long)argv, (unsigned long)envp);
+}
+
--- /dev/null
+#ifndef SISKA_API_H
+#define SISKA_API_H
+
+#include"siska_def.h"
+#include"siska_list.h"
+
+static inline int siska_api_syscall(unsigned long num, unsigned long arg0, unsigned long arg1, unsigned long arg2)
+{
+ int ret;
+
+ asm volatile(
+ "int $0x80\n\t"
+ :"=a"(ret)
+ :"a"(num), "b"(arg0), "c"(arg1), "d"(arg2)
+ :
+ );
+ return ret;
+}
+
+int siska_api_printf(const char* fmt, ...);
+int siska_api_execve(const char* filename, char* const argv, char* const envp);
+
+static inline int siska_api_getpid()
+{
+ return siska_api_syscall(SISKA_SYSCALL_GETPID, 0, 0, 0);
+}
+
+static inline int siska_api_getppid()
+{
+ return siska_api_syscall(SISKA_SYSCALL_GETPPID, 0, 0, 0);
+}
+
+
+#endif
+
--- /dev/null
+#ifndef SISKA_ATOMIC_H
+#define SISKA_ATOMIC_H
+
+typedef struct {
+ volatile int refs;
+} siska_atomic_t;
+
+typedef struct {
+ siska_atomic_t v;
+} siska_spinlock_t;
+
+#define LOCK "lock;"
+
+
+static inline int siska_atomic_xchg(siska_atomic_t* v, int i)
+{
+ asm volatile("xchg %0, %1"
+ :"=m"(v->refs), "=r"(i)
+ :"1"(i)
+ :
+ );
+ return i;
+}
+
+static inline void siska_atomic_inc(siska_atomic_t* v)
+{
+ asm volatile(LOCK"incl %0":"=m"(v->refs) ::);
+}
+
+static inline void siska_atomic_dec(siska_atomic_t* v)
+{
+ asm volatile(LOCK"decl %0":"=m"(v->refs) ::);
+}
+
+static inline int siska_atomic_dec_and_test(siska_atomic_t* v)
+{
+ char ret;
+ asm volatile(LOCK"decl %0; setz %1":"=m"(v->refs), "=r"(ret)::);
+ return ret;
+}
+
+static inline void siska_cli()
+{
+ asm volatile("cli":::);
+}
+static inline void siska_sti()
+{
+ asm volatile("sti":::);
+}
+
+#define SISKA_SPINLOCK_INIT {0}
+
+static inline void siska_spinlock_init(siska_spinlock_t* lock)
+{
+ lock->v.refs = 0;
+}
+
+#define siska_irqsave(flags) \
+ do { \
+ asm volatile( \
+ "pushfl\n\t" \
+ "popl %0\n\t" \
+ :"=r"(flags) \
+ : \
+ : \
+ ); \
+ siska_cli(); \
+ } while (0)
+
+#define siska_irqrestore(flags) \
+ do { \
+ asm volatile( \
+ "pushl %0\n\t" \
+ "popfl\n\t" \
+ : \
+ :"r"(flags) \
+ :"flags" \
+ ); \
+ } while (0)
+
+#undef SISKA_SMP
+
+#ifdef SISKA_SMP
+#define siska_spin_lock_irqsave(lock, flags) \
+ do { \
+ siska_irqsave(flags); \
+ while(0 != siska_atomic_xchg(&lock->v, 1)); \
+ } while (0)
+
+#define siska_spin_unlock_irqrestore(lock, flags) \
+ do { \
+ lock->v.refs = 0; \
+ siska_irqrestore(flags); \
+ } while (0)
+
+#define siska_spin_lock(lock) \
+ do { \
+ while(0 != siska_atomic_xchg(&lock->v, 1)); \
+ } while (0)
+
+#define siska_spin_unlock(lock) \
+ do { \
+ lock->v.refs = 0; \
+ } while (0)
+
+#else
+#define siska_spin_lock_irqsave(lock, flags) siska_irqsave(flags)
+#define siska_spin_unlock_irqrestore(lock, flags) siska_irqrestore(flags)
+#define siska_spin_lock(lock)
+#define siska_spin_unlock(lock)
+#endif
+
+#endif
+
--- /dev/null
+
+#include"siska_task.h"
+#include"siska_mm.h"
+
+static int console_x = 0;
+static int console_y = 0;
+
+static int console_rows = 25;
+static int console_cols = 80;
+
+void siska_console_init()
+{
+ console_x = 0;
+ console_y = 0;
+
+ console_rows = 25;
+ console_cols = 80;
+}
+
+int siska_console_write(const char* fmt)
+{
+ unsigned char* buf = (unsigned char*)0xb8000;
+ unsigned char* p = (unsigned char*)fmt;
+
+ unsigned long flags;
+ siska_irqsave(flags);
+ while (*p) {
+
+ if (console_x >= console_cols) {
+ console_x = 0;
+ console_y++;
+
+ if (console_y >= console_rows)
+ console_y = 0;
+ }
+
+ if ('\n' == *p) {
+ p++;
+ console_x = 0;
+ console_y++;
+ if (console_y >= console_rows)
+ console_y = 0;
+ continue;
+ }
+
+ int pos = console_y * console_cols + console_x;
+
+ buf[pos * 2] = *p++;
+ buf[pos * 2 + 1] = 0x0f;
+
+ console_x++;
+ }
+ siska_irqrestore(flags);
+
+ return (int)(p - (unsigned char*)fmt);
+}
+
+static char printk_buf[128];
+
+int siska_printk(const char* fmt, ...)
+{
+ siska_va_list ap;
+ unsigned long flags;
+
+ siska_irqsave(flags);
+ siska_va_start(ap, fmt);
+ int n = siska_vsnprintf(printk_buf, sizeof(printk_buf), fmt, ap);
+ siska_va_end(ap);
+
+ if (n > 0)
+ n = siska_console_write(printk_buf);
+
+ siska_irqrestore(flags);
+ return n;
+}
+
--- /dev/null
+#ifndef SISKA_CORE_H
+#define SISKA_CORE_H
+
+#include"siska_def.h"
+#include"siska_list.h"
+
+typedef struct siska_task_s siska_task_t;
+typedef struct siska_tss_s siska_tss_t;
+typedef struct siska_mm_s siska_mm_t;
+
+typedef struct siska_vfs_s siska_vfs_t;
+typedef struct siska_fs_s siska_fs_t;
+typedef struct siska_file_ops_s siska_file_ops_t;
+typedef struct siska_file_s siska_file_t;
+typedef struct siska_dev_s siska_dev_t;
+
+typedef struct siska_sblock_s siska_sblock_t;
+typedef struct siska_inode_s siska_inode_t;
+
+typedef struct siska_sblock_dev_s siska_sblock_dev_t;
+typedef struct siska_inode_dev_s siska_inode_dev_t;
+
+#define PG_SHIFT 12
+#define PG_SIZE (1u << PG_SHIFT)
+
+#define PGDIR_KERNEL 0
+
+extern volatile unsigned long _jiffies;
+
+#define SISKA_INTERRUPT_PAGE_FAULT 14
+#define SISKA_INTERRUPT_TIMER 0x20
+#define SISKA_INTERRUPT_SYSCALL 0x80
+
+#define get_asm_addr(_id) \
+ ({ \
+ void* addr; \
+ asm volatile("lea "#_id", %0\n\t" :"=r"(addr)::); \
+ addr; \
+ })
+
+static inline void switch_to_pgdir(unsigned long pgdir)
+{
+ asm volatile(
+ "movl %0, %%cr3\n\t"
+ "jmp 1f\n\t"
+ "1:\n\t"
+ :
+ :"r"(pgdir)
+ :
+ );
+}
+
+static inline unsigned long get_jiffies()
+{
+ unsigned long jiffies;
+ asm volatile(
+ "lea _jiffies, %0\n\t"
+ "movl (%0), %0\n\t"
+ :"=r"(jiffies)
+ :
+ :
+ );
+ return jiffies;
+}
+
+static inline siska_task_t* get_current()
+{
+ siska_task_t* current;
+ asm volatile(
+ "andl %%esp, %0"
+ :"=r"(current)
+ :"0"(~(PG_SIZE - 1))
+ :
+ );
+ return current;
+}
+#define current get_current()
+
+#define set_gate_handler(num, type, handler) \
+ do { \
+ asm volatile( \
+ "lea "#handler", %%edx\n\t" \
+ "movl $0x00080000, %%eax\n\t" \
+ "movw %%dx, %%ax\n\t" \
+ "movw %1, %%dx\n\t" \
+ "lea _idt(, %0, 8), %0\n\t" \
+ "movl %%eax, (%0)\n\t" \
+ "movl %%edx, 4(%0)\n\t" \
+ : \
+ :"r"(num), "i"(type) \
+ :"eax", "edx" \
+ ); \
+ } while (0)
+#define set_intr_handler(num, handler) set_gate_handler(num, 0x8e00, handler)
+#define set_trap_handler(num, handler) set_gate_handler(num, 0xef00, handler)
+
+#define set_syscall_handler(num, handler) \
+ do { \
+ asm volatile( \
+ "lea "#handler", %%eax\n\t" \
+ "movl %%eax, _syscall_table(, %0, 4)\n\t" \
+ : \
+ :"r"(num) \
+ :"eax" \
+ ); \
+ } while (0)
+
+static inline void outb_p(unsigned char data, unsigned short port)
+{
+ asm volatile(
+ "movb %0, %%al\n\t"
+ "outb %%al, %1\n\t"
+ "jmp 1f\n\t"
+ "1: jmp 1f\n\t"
+ "1:\n\t"
+ :
+ :"r"(data), "i"(port)
+ :
+ );
+}
+static inline void outb(unsigned char data, unsigned short port)
+{
+ asm volatile(
+ "movb %0, %%al\n\t"
+ "outb %%al, %1\n\t"
+ :
+ :"r"(data), "i"(port)
+ :
+ );
+}
+static inline unsigned char inb_p(unsigned short port)
+{
+ unsigned char data;
+ asm volatile(
+ "inb %1, %%al\n\t"
+ "movb %%al, %0\n\t"
+ "jmp 1f\n\t"
+ "1: jmp 1f\n\t"
+ "1:\n\t"
+ :"=r"(data)
+ :"i"(port)
+ :
+ );
+ return data;
+}
+
+int siska_console_write(const char* fmt);
+#ifdef ON_BOCHS
+int siska_printk(const char* fmt, ...);
+#else
+#define siska_printk printf
+#endif
+
+#endif
+
--- /dev/null
+#ifndef SISKA_DEF_H
+#define SISKA_DEF_H
+
+#define ON_BOCHS
+#ifdef ON_BOCHS
+#define NULL ((void*)0)
+
+typedef char* siska_va_list;
+#define INTSIZEOF(n) ((sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1))
+#define siska_va_start(ap,v) (ap = (siska_va_list)&v + INTSIZEOF(v))
+#define siska_va_arg(ap,t) (*(t*)((ap += INTSIZEOF(t)) - INTSIZEOF(t)))
+#define siska_va_end(ap) (ap = (siska_va_list)0)
+
+#else
+#include<stdio.h>
+#include<stdarg.h>
+#define siska_va_list va_list
+#define siska_va_start va_start
+#define siska_va_arg va_arg
+#define siska_va_end va_end
+#endif
+
+#include"siska_atomic.h"
+#include"siska_string.h"
+
+#define SISKA_SYSCALL_FORK 1
+#define SISKA_SYSCALL_SCHED 2
+#define SISKA_SYSCALL_WRITE 3
+#define SISKA_SYSCALL_KILL 4
+#define SISKA_SYSCALL_SIGNAL 5
+#define SISKA_SYSCALL_EXIT 6
+#define SISKA_SYSCALL_WAIT 7
+#define SISKA_SYSCALL_GETPID 8
+#define SISKA_SYSCALL_GETPPID 9
+#define SISKA_SYSCALL_EXECVE 10
+
+#define SISKA_SIGINT 2
+#define SISKA_SIGKILL 9
+#define SISKA_SIGSEGV 11
+#define SISKA_SIGCHLD 17
+#define SISKA_NB_SIGNALS (sizeof(unsigned long) * 8)
+#define SISKA_SIG_DFL NULL
+#define SISKA_SIG_IGN ((void*)0x1)
+
+int siska_vsnprintf(char* buf, int size, const char* fmt, siska_va_list ap);
+int siska_snprintf (char* buf, int size, const char* fmt, ...);
+
+#endif
+
--- /dev/null
+#include"siska_vfs.h"
+#include"siska_mm.h"
+
+int memory_dev_open(siska_file_t* file, int flags, unsigned int mode)
+{
+ if (file && file->dev) {
+
+ if (file->dev->priv && file->dev->priv_size > 0) {
+ file->dev->priv_pos = 0;
+ return 0;
+ }
+ }
+ return -1;
+}
+
+int memory_dev_close(siska_file_t* file)
+{
+ return 0;
+}
+
+int memory_dev_read(siska_file_t* file, void* buf, int size)
+{
+ if (!file || !buf || size < 0)
+ return -1;
+
+ siska_dev_t* dev = file->dev;
+
+ if (!dev || !dev->priv || dev->priv_size <= 0)
+ return -1;
+
+ int len = dev->priv_size - dev->priv_pos;
+ if (len < 0)
+ return -1;
+
+ len = size > len ? len : size;
+
+// siska_printk("%s(), %d, dev p: %p, len: %d\n", __func__, __LINE__, dev->priv + dev->priv_pos, len);
+
+ siska_memcpy(buf, dev->priv + dev->priv_pos, len);
+ dev->priv_pos += len;
+
+ return len;
+}
+
+int memory_dev_write(siska_file_t* file, const void* buf, int size)
+{
+ if (!file || !buf || size < 0)
+ return -1;
+
+ siska_dev_t* dev = file->dev;
+
+ if (!dev || !dev->priv || dev->priv_size <= 0)
+ return -1;
+
+ int len = dev->priv_size - dev->priv_pos;
+ if (len < 0)
+ return -1;
+
+ len = size > len ? len : size;
+
+ siska_memcpy(dev->priv + dev->priv_pos, buf, len);
+ dev->priv_pos += len;
+
+ return len;
+}
+
+int memory_dev_lseek(siska_file_t* file, long offset, int whence)
+{
+ if (!file || !file->dev || offset < 0 || SISKA_SEEK_SET != whence)
+ return -1;
+
+ file->dev->priv_pos = offset;
+// siska_printk("%s(), %d, dev->priv_pos: %d\n", __func__, __LINE__, file->dev->priv_pos);
+ return 0;
+}
+
+int memory_dev_sync(siska_file_t* file)
+{
+ return 0;
+}
+
+int memory_dev_ioctl(siska_file_t* file, unsigned long cmd, ...)
+{
+ return 0;
+}
+
+
+siska_file_ops_t siska_fops_memory_dev =
+{
+ .type = "memory_dev",
+
+ .next = NULL,
+
+ .open = memory_dev_open,
+ .close = memory_dev_close,
+
+ .read = memory_dev_read,
+ .write = memory_dev_write,
+
+ .lseek = memory_dev_lseek,
+ .sync = memory_dev_sync,
+
+ .ioctl = memory_dev_ioctl,
+};
+
--- /dev/null
+#ifndef SISKA_FS_H
+#define SISKA_FS_H
+
+#include"siska_vfs.h"
+
+// super block, 512
+// inode, 244 * 8 * sizeof(inode_dev)
+// block, 244 * 8 * (1024 << sblock_dev->block_size)
+
+#define SISKA_FS0_NB_INODES (16u << 3)
+#define SISKA_FS0_NB_BLOCKS (16u << 3)
+#define SISKA_FS0_INODE_START (sizeof(siska_sblock_dev_t))
+#define SISKA_FS0_BLOCK_START (sizeof(siska_sblock_dev_t) + SISKA_FS0_NB_INODES * sizeof(siska_inode_dev_t))
+
+struct siska_sblock_dev_s
+{
+ unsigned char magic[7];
+ unsigned char block_size;
+
+ union {
+ unsigned long next;
+ unsigned char fill[8];
+ };
+
+ unsigned char inode_map[SISKA_FS0_NB_INODES >> 3];
+ unsigned char block_map[SISKA_FS0_NB_BLOCKS >> 3];
+ unsigned char reserved[8];
+};
+
+struct siska_inode_dev_s
+{
+ union {
+ unsigned long size;
+ unsigned char fill0[8];
+ };
+#define SISKA_INODE_NAME_OFFSET (1u << 29)
+ union {
+ unsigned long mode;
+ unsigned char fill1[8];
+ };
+
+ union {
+ unsigned long block_offset;
+ unsigned char fill2[8];
+ };
+
+ union {
+ unsigned long block_count;
+ unsigned char fill3[8];
+ };
+
+ union {
+ unsigned long inode_parent;
+ unsigned char fill4[8];
+ };
+
+ union {
+ unsigned long name_parent_offset;
+ unsigned char name[8];
+ };
+};
+
+typedef struct siska_dir_dev_s siska_dir_dev_t;
+
+struct siska_dir_dev_s
+{
+ union {
+ unsigned long inode_index;
+ unsigned char fill0[8];
+ };
+
+ union {
+ unsigned long name_len;
+ unsigned char fill1[8];
+ };
+
+ unsigned char name[0]; // string ended by '\0'
+};
+
+#endif
+
--- /dev/null
+#include"siska_vfs.h"
+#include"siska_fs.h"
+#include"siska_mm.h"
+
+extern siska_vfs_t siska_fs_siska0;
+
+int siska0_find_in_dir(siska_dir_dev_t* dir_dev, siska_inode_dev_t* inode_dev, const char* filename, siska_fs_t* fs)
+{
+ unsigned long block_size;
+ unsigned long offset;
+ unsigned long i;
+
+ block_size = 1024 << fs->sblock->sblock_dev->block_size;
+
+ offset = SISKA_FS0_BLOCK_START + inode_dev->block_offset * block_size;
+
+ int ret = fs->dev->fops->lseek(fs->dir, offset, SISKA_SEEK_SET);
+ if (ret < 0)
+ return -1;
+
+ siska_printk("%s(), %d, filename: %s\n", __func__, __LINE__, filename);
+// siska_printk("%s(), %d, offset: %d, block_offset: %d, block_size: %d\n", __func__, __LINE__, offset, inode_dev->block_offset, block_size);
+
+ siska_printk("%s(), %d, inode_dev->size: %d\n", __func__, __LINE__, inode_dev->size);
+
+ for (i = 0; i < inode_dev->size; ) {
+
+ ret = fs->dev->fops->read(fs->dir, dir_dev, sizeof(siska_dir_dev_t));
+ if (ret != sizeof(siska_dir_dev_t))
+ return -1;
+ i += ret;
+
+ if (i + dir_dev->name_len > inode_dev->size)
+ return -1;
+
+ char* name = siska_kmalloc(dir_dev->name_len);
+ if (!name)
+ return -1;
+
+ ret = fs->dev->fops->read(fs->dir, name, dir_dev->name_len);
+ if (ret != dir_dev->name_len) {
+ siska_kfree(name);
+ return -1;
+ }
+ i += ret;
+
+ if (!siska_strcmp(filename, name)) {
+ siska_printk("%s(), %d, filename: %s, name: %s\n", __func__, __LINE__, filename, name);
+ siska_kfree(name);
+ return 0;
+ }
+
+ siska_kfree(name);
+ }
+
+ siska_printk("%s(), %d, inode_dev->size: %d\n", __func__, __LINE__, inode_dev->size);
+ return -404;
+}
+
+int siska0_read_inode(siska_file_t* file, siska_fs_t* fs, siska_inode_dev_t* inode_dev, unsigned long index)
+{
+ siska_inode_t* inode;
+ unsigned long offset;
+
+ offset = SISKA_FS0_INODE_START + index * sizeof(siska_inode_dev_t);
+
+ int ret = fs->dev->fops->lseek(fs->dir, offset, SISKA_SEEK_SET);
+ if (ret < 0)
+ return -1;
+
+ ret = fs->dev->fops->read(fs->dir, inode_dev, sizeof(siska_inode_dev_t));
+ if (ret != sizeof(siska_inode_dev_t))
+ return -1;
+
+ inode = siska_inode_alloc();
+ if (!inode)
+ return -1;
+
+ inode->file = file;
+ inode->sblock = fs->sblock;
+ inode->index = index;
+ inode->inode_dev = inode_dev;
+
+ file->inode = inode;
+ return 0;
+}
+
+static unsigned long __siska0_find_blocks(siska_sblock_dev_t* sblock_dev, unsigned int nblocks)
+{
+ unsigned long block_index = 0;
+ unsigned long k = 0;
+ unsigned long i;
+ unsigned long j;
+
+ for (i = 0; i < sizeof(sblock_dev->block_map); i++) {
+
+ for (j = 0; j < 8; j++) {
+
+ if (sblock_dev->block_map[i] & (1u << j)) {
+ k = 0;
+ continue;
+ }
+
+ if (0 == k)
+ block_index = i * 8 + j;
+
+ if (++k == nblocks)
+ return block_index;
+ }
+ }
+ return 0;
+}
+
+static void __siska0_blocks_set_used(siska_sblock_dev_t* sbd, unsigned long block_index, unsigned int nblocks)
+{
+ unsigned long i;
+ unsigned long j;
+ unsigned long k;
+
+ for (k = 0; k < nblocks; k++) {
+ i = (block_index + k) >> 3;
+ j = (block_index + k) & 0x7;
+
+ sbd->block_map[i] |= 1u << j;
+ }
+}
+
+static void __siska0_blocks_set_free(siska_sblock_dev_t* sbd, unsigned long block_index, unsigned int nblocks)
+{
+ unsigned long i;
+ unsigned long j;
+ unsigned long k;
+
+ for (k = 0; k < nblocks; k++) {
+ i = (block_index + k) >> 3;
+ j = (block_index + k) & 0x7;
+
+ sbd->block_map[i] &= ~(1u << j);
+ }
+}
+
+static int __siska0_realloc_blocks(siska_fs_t* fs, siska_sblock_dev_t* sbd, siska_inode_dev_t* inode_dev, unsigned long append_size)
+{
+ unsigned long block_size = 1024 << sbd->block_size;
+
+ unsigned long empty_len = inode_dev->block_count * block_size - inode_dev->size;
+
+ if (empty_len >= append_size)
+ return 0;
+
+ empty_len = append_size - empty_len;
+
+ unsigned long nblocks = (empty_len + block_size - 1) / block_size;
+
+ unsigned long block_index = inode_dev->block_offset + inode_dev->block_count;
+ unsigned long i;
+ unsigned long j;
+ unsigned long k;
+
+ for (k = 0; k < nblocks; k++) {
+ i = (block_index + k) / 8;
+ j = (block_index + k) % 8;
+
+ if (sbd->block_map[i] & (1u << j))
+ break;
+ }
+
+ if (k == nblocks) {
+
+ __siska0_blocks_set_used(sbd, block_index, nblocks);
+
+ inode_dev->block_count += nblocks;
+ return 0;
+ }
+
+ nblocks += inode_dev->block_count;
+
+ block_index = __siska0_find_blocks(sbd, nblocks);
+ if (0 == block_index)
+ return -1;
+
+ char* buf = siska_kmalloc(1024);
+ if (!buf)
+ return -1;
+
+ for (i = 0; i < inode_dev->size; ) {
+
+ unsigned long offset;
+
+ offset = SISKA_FS0_BLOCK_START + inode_dev->block_offset * block_size;
+ offset += i;
+ int ret = fs->dev->fops->lseek(fs->dir, offset, SISKA_SEEK_SET);
+ if (ret < 0) {
+ siska_kfree(buf);
+ return -1;
+ }
+
+ k = inode_dev->size - i;
+ k = k > 1024 ? 1024 : k;
+ ret = fs->dev->fops->read(fs->dir, buf, k);
+ if (ret != k) {
+ siska_kfree(buf);
+ return -1;
+ }
+
+ offset = SISKA_FS0_BLOCK_START + block_index * block_size;
+ offset += i;
+ ret = fs->dev->fops->lseek(fs->dir, offset, SISKA_SEEK_SET);
+ if (ret < 0) {
+ siska_kfree(buf);
+ return -1;
+ }
+
+ ret = fs->dev->fops->read(fs->dir, buf, k);
+ if (ret != k) {
+ siska_kfree(buf);
+ return -1;
+ }
+
+ i += k;
+ }
+
+ siska_kfree(buf);
+ buf = NULL;
+
+ __siska0_blocks_set_free(sbd, inode_dev->block_offset, inode_dev->block_count);
+
+ __siska0_blocks_set_used(sbd, block_index, nblocks);
+
+ inode_dev->block_offset = block_index;
+ inode_dev->block_count = nblocks;
+ return 0;
+}
+
+int siska0_write_dir(siska_file_t* file, siska_fs_t* fs, siska_inode_dev_t* parent, unsigned long parent_index)
+{
+ siska_dir_dev_t* dir_dev;
+ unsigned long block_size;
+ unsigned long offset;
+ unsigned long i;
+
+ unsigned long empty_pos = 0;
+ unsigned long empty_len = 0;
+ unsigned long filename_len = siska_strlen(file->name) + 1;
+
+ dir_dev = siska_kmalloc(sizeof(siska_dir_dev_t));
+ if (!dir_dev)
+ return -1;
+
+ block_size = 1024 << fs->sblock->sblock_dev->block_size;
+
+ offset = SISKA_FS0_BLOCK_START + parent->block_offset * block_size;
+
+ int ret = fs->dev->fops->lseek(fs->dir, offset, SISKA_SEEK_SET);
+ if (ret < 0)
+ goto _error;
+
+ for (i = 0; i < parent->size; ) {
+
+ ret = fs->dev->fops->read(fs->dir, dir_dev, sizeof(siska_dir_dev_t));
+ if (ret != sizeof(siska_dir_dev_t))
+ goto _error;
+ i += ret;
+
+ if (i + dir_dev->name_len > parent->size)
+ goto _error;
+
+ if (0 == dir_dev->inode_index && dir_dev->name_len >= filename_len) {
+ if (empty_len > dir_dev->name_len) {
+ empty_len = dir_dev->name_len;
+ empty_pos = i - ret;
+ }
+ }
+
+ char* name = siska_kmalloc(dir_dev->name_len);
+ if (!name)
+ goto _error;
+
+ ret = fs->dev->fops->read(fs->dir, name, dir_dev->name_len);
+ if (ret != dir_dev->name_len) {
+ siska_kfree(name);
+ goto _error;
+ }
+ i += ret;
+
+ if (!siska_strcmp(file->name, name)) {
+ siska_kfree(name);
+ goto _error;
+ }
+
+ siska_kfree(name);
+ }
+
+ if (0 == empty_len) {
+
+ unsigned long append_size = filename_len + sizeof(siska_dir_dev_t);
+
+ ret = __siska0_realloc_blocks(fs, fs->sblock->sblock_dev, parent, append_size);
+ if (ret < 0)
+ goto _error;
+
+ empty_len = parent->block_count * block_size - parent->size;
+ empty_pos = parent->size;
+ }
+
+ if (empty_len > 0) {
+ offset = SISKA_FS0_BLOCK_START + parent->block_offset * block_size;
+ offset += empty_pos;
+
+ ret = fs->dev->fops->lseek(fs->dir, offset, SISKA_SEEK_SET);
+ if (ret < 0)
+ goto _error;
+
+ dir_dev->inode_index = file->inode->index;
+ dir_dev->name_len = filename_len;
+
+ ret = fs->dev->fops->write(fs->dir, dir_dev, sizeof(siska_dir_dev_t));
+ if (ret != sizeof(siska_dir_dev_t))
+ goto _error;
+
+ ret = fs->dev->fops->write(fs->dir, file->name, filename_len);
+ if (ret != filename_len)
+ goto _error;
+
+ if (empty_pos == parent->size)
+ parent->size += sizeof(siska_dir_dev_t) + filename_len;
+
+ siska_printk("%s(), %d, parent->size: %d\n", __func__, __LINE__, parent->size);
+
+ offset = SISKA_FS0_INODE_START + sizeof(siska_inode_dev_t) * parent_index;
+ ret = fs->dev->fops->lseek(fs->dir, offset, SISKA_SEEK_SET);
+ if (ret < 0)
+ goto _error;
+
+ ret = fs->dev->fops->write(fs->dir, parent, sizeof(siska_inode_dev_t));
+ if (ret != sizeof(siska_inode_dev_t))
+ goto _error;
+ return 0;
+ }
+
+_error:
+ siska_kfree(dir_dev);
+ return -1;
+}
+
+int siska0_create_inode(siska_file_t* file, siska_fs_t* fs, siska_inode_dev_t* parent, unsigned long parent_index)
+{
+ siska_sblock_dev_t* sblock_dev;
+ siska_sblock_t* sblock;
+
+ siska_inode_dev_t* inode_dev;
+ siska_inode_t* inode;
+
+ unsigned long i;
+ unsigned long j;
+ unsigned long index;
+
+ sblock = fs->sblock;
+
+ while (sblock) {
+
+ sblock_dev = sblock->sblock_dev;
+
+ for (i = 0; i < sizeof(sblock_dev->inode_map); i++) {
+
+ if (0xff == sblock_dev->inode_map[i])
+ continue;
+
+ for (j = 0; j < 8; j++) {
+
+ if (0 == i && 0 == j)
+ continue;
+
+ if (!(sblock_dev->inode_map[i] & (1u << j)))
+ goto _found;
+ }
+ }
+
+ sblock = sblock->next;
+ }
+ return -1;
+
+_found:
+ inode = siska_inode_alloc();
+ if (!inode)
+ return -1;
+
+ inode_dev = siska_kmalloc(sizeof(siska_inode_dev_t));
+ if (!inode_dev) {
+ siska_inode_free(inode);
+ return -1;
+ }
+
+ inode_dev->size = 0;
+ inode_dev->block_offset = 0;
+ inode_dev->block_count = 0;
+
+ if (file->parent->fs == fs)
+ inode_dev->inode_parent = 0;
+ else
+ inode_dev->inode_parent = file->parent->inode->index;
+
+ inode_dev->name_parent_offset = 0;
+
+ inode->index = i * 8 + j;
+ inode->file = file;
+ inode->sblock = sblock;
+ inode->inode_dev = inode_dev;
+
+ file->inode = inode;
+
+ if (siska0_write_dir(file, fs, parent, parent_index) < 0) {
+ siska_inode_free(inode);
+ return -1;
+ }
+
+ sblock_dev->inode_map[i] |= 1u << j;
+
+ int ret = fs->dev->fops->lseek(fs->dir, 0, SISKA_SEEK_SET);
+ if (ret < 0) {
+ siska_inode_free(inode);
+ return -1;
+ }
+
+ ret = fs->dev->fops->write(fs->dir, sblock_dev, sizeof(siska_sblock_dev_t));
+ if (ret != sizeof(siska_sblock_dev_t)) {
+ siska_inode_free(inode);
+ return -1;
+ }
+
+ inode->next = sblock->inodes;
+ sblock->inodes = inode;
+ return 0;
+}
+
+int siska0_open_in_sblock(siska_file_t* file, siska_fs_t* fs, int flags, unsigned int mode)
+{
+ siska_inode_dev_t* inode_dev;
+ siska_dir_dev_t* dir_dev;
+ unsigned long block_size;
+
+ inode_dev = siska_kmalloc(sizeof(siska_inode_dev_t));
+ if (!inode_dev)
+ return -1;
+
+ dir_dev = siska_kmalloc(sizeof(siska_dir_dev_t));
+ if (!dir_dev) {
+ siska_kfree(inode_dev);
+ return -1;
+ }
+
+ // read first inode
+ int ret = fs->dev->fops->lseek(fs->dir, SISKA_FS0_INODE_START, SISKA_SEEK_SET);
+ if (ret < 0)
+ goto _error;
+
+ ret = fs->dev->fops->read(fs->dir, inode_dev, sizeof(siska_inode_dev_t));
+ if (ret != sizeof(siska_inode_dev_t))
+ goto _error;
+
+ siska_printk("%s(), %d, inode_dev->size: %d\n", __func__, __LINE__, inode_dev->size);
+
+ // read sub dirs of fs rootdir
+ ret = siska0_find_in_dir(dir_dev, inode_dev, file->name, fs);
+ if (-1 == ret)
+ goto _error;
+
+ if (-404 == ret) {
+ siska_printk("%s(), %d, file->name: %s, ret: %d\n", __func__, __LINE__, file->name, ret);
+
+ ret = siska0_create_inode(file, fs, inode_dev, 0);
+
+ siska_printk("%s(), %d, file->name: %s, ret: %d\n", __func__, __LINE__, file->name, ret);
+ } else {
+ ret = siska0_read_inode(file, fs, inode_dev, dir_dev->inode_index);
+
+ siska_printk("%s(), %d, file->name: %s, ret: %d\n", __func__, __LINE__, file->name, ret);
+ }
+
+ if (ret < 0)
+ goto _error;
+
+ siska_kfree(dir_dev);
+ return 0;
+
+_error:
+ siska_kfree(inode_dev);
+ siska_kfree(dir_dev);
+ return -1;
+}
+
+int siska0_recursive_open(siska_file_t* file, siska_fs_t* fs, int flags, unsigned int mode)
+{
+ if (!file->parent)
+ return -1;
+
+ siska_printk("%s(), %d, file->name: %s, type: %d\n", __func__, __LINE__, file->name, siska_file_type(file));
+
+ if (file->parent->fs == fs)
+ return siska0_open_in_sblock(file, fs, flags, mode);
+
+ if (!file->parent->inode || !file->parent->inode->inode_dev) {
+
+ int ret = siska0_recursive_open(file->parent, fs, file->parent->flags, 0);
+ if (ret < 0) {
+ siska_printk("%s(), %d, file->parent: %s\n", __func__, __LINE__, file->parent->name);
+ return -1;
+ }
+ }
+
+ siska_inode_dev_t* inode_dev;
+ siska_dir_dev_t* dir_dev;
+
+ dir_dev = siska_kmalloc(sizeof(siska_dir_dev_t));
+ if (!dir_dev)
+ return -1;
+
+ int ret = siska0_find_in_dir(dir_dev, file->parent->inode->inode_dev, file->name, fs);
+ if (-1 == ret) {
+ siska_kfree(dir_dev);
+ return -1;
+ }
+
+ siska_printk("%s(), %d, ret: %d, file->name: %s, type: %d\n", __func__, __LINE__, ret, file->name, siska_file_type(file));
+
+ if (-404 == ret) {
+
+ ret = siska0_create_inode(file, fs, file->parent->inode->inode_dev, file->parent->inode->index);
+
+ } else {
+ inode_dev = siska_kmalloc(sizeof(siska_inode_dev_t));
+ if (!inode_dev) {
+ siska_kfree(dir_dev);
+ return -1;
+ }
+
+ ret = siska0_read_inode(file, fs, inode_dev, dir_dev->inode_index);
+ if (ret < 0)
+ siska_kfree(inode_dev);
+ }
+
+ siska_kfree(dir_dev);
+ return ret;
+}
+
+int siska0_open(siska_file_t* file, int flags, unsigned int mode)
+{
+ if (!file || !file->name)
+ return -1;
+
+ siska_fs_t* fs;
+
+ fs = siska_vfs_find_fs(file->parent);
+ if (!fs)
+ return -1;
+
+ if (!fs->sblock || !fs->sblock->sblock_dev)
+ return -1;
+
+ if (siska_strncmp(fs->sblock->sblock_dev->magic, "siska00", 7))
+ return -1;
+
+ return siska0_recursive_open(file, fs, flags, mode);
+}
+
+int siska0_close(siska_file_t* file)
+{
+ return 0;
+}
+
+int siska0_read(siska_file_t* file, void* buf, int size)
+{
+ if (!file || !buf || size < 0)
+ return -1;
+
+ if (!file->inode || !file->inode->inode_dev)
+ return -1;
+
+ if (0 == size)
+ return 0;
+
+ siska_fs_t* fs;
+
+ fs = siska_vfs_find_fs(file->parent);
+ if (!fs)
+ return -1;
+
+ siska_sblock_dev_t* sblock_dev = file->inode->sblock->sblock_dev;
+ siska_inode_dev_t* inode_dev = file->inode->inode_dev;
+
+ if (size > inode_dev->size - file->offset)
+ size = inode_dev->size - file->offset;
+
+ if (0 == size)
+ return 0;
+
+ unsigned long block_size = 1024u << sblock_dev->block_size;
+
+ unsigned long offset = SISKA_FS0_BLOCK_START
+ + inode_dev->block_offset * block_size
+ + file->offset;
+
+ int ret = fs->dev->fops->lseek(fs->dir, offset, SISKA_SEEK_SET);
+ if (ret < 0)
+ return -1;
+
+ ret = fs->dev->fops->read(fs->dir, buf, size);
+ if (ret != size)
+ return -1;
+
+ file->offset += size;
+ return ret;
+}
+
+int siska0_write(siska_file_t* file, const void* buf, int size)
+{
+ if (!file || !buf || size < 0)
+ return -1;
+
+ if (!file->inode || !file->inode->inode_dev)
+ return -1;
+
+ if (0 == size)
+ return 0;
+
+ siska_fs_t* fs;
+
+ fs = siska_vfs_find_fs(file->parent);
+ if (!fs)
+ return -1;
+
+ siska_sblock_dev_t* sblock_dev = file->inode->sblock->sblock_dev;
+ siska_inode_dev_t* inode_dev = file->inode->inode_dev;
+
+ unsigned long block_size = 1024u << sblock_dev->block_size;
+ unsigned long nblocks = (file->offset + size + block_size - 1) / block_size;
+
+ if (0 == inode_dev->block_offset) {
+
+ inode_dev->block_offset = __siska0_find_blocks(sblock_dev, nblocks);
+
+ if (0 == inode_dev->block_offset)
+ return -1;
+
+ inode_dev->block_count = nblocks;
+
+ __siska0_blocks_set_used(sblock_dev, inode_dev->block_offset, nblocks);
+
+ } else if (nblocks > inode_dev->block_count) {
+
+ unsigned long append_size = (nblocks - inode_dev->block_count) * block_size;
+
+ int ret = __siska0_realloc_blocks(fs, sblock_dev, inode_dev, append_size);
+ if (ret < 0)
+ return -1;
+ }
+
+ unsigned long offset = SISKA_FS0_BLOCK_START
+ + inode_dev->block_offset * block_size
+ + file->offset;
+
+ int ret = fs->dev->fops->lseek(fs->dir, offset, SISKA_SEEK_SET);
+ if (ret < 0)
+ return -1;
+
+ ret = fs->dev->fops->write(fs->dir, buf, size);
+ if (ret != size)
+ return -1;
+
+ if (inode_dev->size < file->offset + size)
+ inode_dev->size = file->offset + size;
+
+ offset = SISKA_FS0_INODE_START + sizeof(siska_inode_dev_t) * file->inode->index;
+ ret = fs->dev->fops->lseek(fs->dir, offset, SISKA_SEEK_SET);
+ if (ret < 0)
+ return -1;
+
+ ret = fs->dev->fops->write(fs->dir, inode_dev, sizeof(siska_inode_dev_t));
+ if (ret != sizeof(siska_inode_dev_t))
+ return -1;
+ siska_printk("%s(), %d, file->inode->index: %d, inode_dev->size: %d\n",
+ __func__, __LINE__, file->inode->index, inode_dev->size);
+
+ ret = fs->dev->fops->lseek(fs->dir, 0, SISKA_SEEK_SET);
+ if (ret < 0)
+ return -1;
+
+ ret = fs->dev->fops->write(fs->dir, sblock_dev, sizeof(siska_sblock_dev_t));
+ if (ret != sizeof(siska_sblock_dev_t))
+ return -1;
+
+ file->offset += size;
+ return ret;
+}
+
+int siska0_lseek(siska_file_t* file, long offset, int whence)
+{
+ if (!file || offset < 0 || SISKA_SEEK_SET != whence)
+ return -1;
+
+ file->offset = offset;
+ return offset;
+}
+
+int siska0_sync(siska_file_t* file)
+{
+ return -1;
+}
+
+int siska0_ioctl(siska_file_t* file, unsigned long cmd, ...)
+{
+ return -1;
+}
+
+siska_file_ops_t siska_fops_siska0 =
+{
+ .type = "siska0",
+ .next = NULL,
+
+ .open = siska0_open,
+ .close = siska0_close,
+ .read = siska0_read,
+ .write = siska0_write,
+ .lseek = siska0_lseek,
+ .sync = siska0_sync,
+ .ioctl = siska0_ioctl,
+};
+
+int siska0_mkfs(siska_file_t* devfile)
+{
+ siska_sblock_dev_t* sblock_dev;
+ siska_inode_dev_t* inode_dev;
+
+ siska_dev_t* dev;
+
+ if (!devfile || !devfile->dev)
+ return -1;
+
+ dev = devfile->dev;
+
+ if (!dev->fops->write || !dev->fops->lseek)
+ return -1;
+
+ int size = sizeof(siska_sblock_dev_t) + sizeof(siska_inode_dev_t);
+
+ sblock_dev = siska_kmalloc(size);
+ if (!sblock_dev)
+ return -1;
+
+ inode_dev = (siska_inode_dev_t*)((char*)sblock_dev + sizeof(siska_sblock_dev_t));
+
+ sblock_dev->magic[0] = 's';
+ sblock_dev->magic[1] = 'i';
+ sblock_dev->magic[2] = 's';
+ sblock_dev->magic[3] = 'k';
+ sblock_dev->magic[4] = 'a';
+ sblock_dev->magic[5] = '0';
+ sblock_dev->magic[6] = '0';
+
+ sblock_dev->block_size = 0;
+ sblock_dev->next = 0;
+
+ siska_memset(sblock_dev->inode_map, 0, sizeof(sblock_dev->inode_map));
+ siska_memset(sblock_dev->block_map, 0, sizeof(sblock_dev->block_map));
+
+ sblock_dev->inode_map[0] |= 0x1;
+ sblock_dev->block_map[0] |= 0x1;
+
+ inode_dev->size = 0;
+ inode_dev->mode = 0x777;
+ inode_dev->block_offset = 0;
+ inode_dev->block_count = 1;
+ inode_dev->inode_parent = 0xffffffff;
+ inode_dev->name[0] = 'r';
+ inode_dev->name[1] = 'o';
+ inode_dev->name[2] = 'o';
+ inode_dev->name[3] = 't';
+ inode_dev->name[4] = 'd';
+ inode_dev->name[5] = 'i';
+ inode_dev->name[6] = 'r';
+ inode_dev->name[7] = '\0';
+
+ int ret = dev->fops->lseek(devfile, 0, SISKA_SEEK_SET);
+ if (ret < 0)
+ return -1;
+
+ ret = dev->fops->write(devfile, sblock_dev, size);
+ if (ret != size)
+ return -1;
+
+ return 0;
+}
+
+int siska0_mount(siska_fs_t** pfs, siska_file_t* dir, siska_dev_t* dev)
+{
+ siska_sblock_dev_t* sblock_dev;
+ siska_sblock_t* sblock;
+
+ siska_inode_dev_t* inode_dev;
+ siska_inode_t* inode;
+
+ siska_fs_t* fs;
+ int ret;
+
+ if (!pfs || !dir || !dev || !dev->fops)
+ return -1;
+
+ if (!dev->fops->read || !dev->fops->lseek)
+ return -1;
+
+ if (!siska_list_empty(&dir->childs))
+ return -1;
+
+ fs = siska_kmalloc(sizeof(siska_fs_t));
+ if (!fs)
+ return -1;
+
+ dir->dev = dev;
+
+ fs->dir = dir;
+ fs->dev = dev;
+ fs->vfs = &siska_fs_siska0;
+ fs->fops = &siska_fops_siska0;
+ fs->sblock = NULL;
+
+ if (dev->fops->open) {
+ ret = dev->fops->open(dir, SISKA_FILE_FLAG_R | SISKA_FILE_FLAG_W, 0);
+ if (ret < 0) {
+ siska_printk("fs open dev error");
+ goto _open_dev;
+ }
+ }
+
+ unsigned long number = 0;
+ unsigned long block_offset = 0;
+ while (1) {
+ sblock = siska_sblock_alloc();
+ if (!sblock) {
+ siska_printk("fs sblock error");
+ goto _error;
+ }
+
+ sblock_dev = siska_kmalloc(sizeof(siska_sblock_dev_t));
+ if (!sblock_dev) {
+ siska_printk("fs sblock dev error");
+
+ siska_kfree(sblock);
+ goto _error;
+ }
+ sblock->sblock_dev = sblock_dev;
+ sblock->number = number++;
+
+ siska_sblock_t** pp = &fs->sblock;
+ while (*pp)
+ pp = &(*pp)->next;
+ *pp = sblock;
+
+ ret = dev->fops->read(dir, sblock_dev, sizeof(siska_sblock_dev_t));
+ if (ret != sizeof(siska_sblock_dev_t)) {
+ siska_printk("fs sblock read error");
+ goto _error;
+ }
+
+ if (siska_strncmp(sblock_dev->magic, "siska00", 7)) {
+ siska_printk("fs magic error");
+ goto _error;
+ }
+
+ if (0 == sblock_dev->next)
+ break;
+
+ block_offset += sizeof(siska_sblock_dev_t);
+ block_offset += sizeof(siska_inode_dev_t) * 8 * sizeof(sblock_dev->inode_map);
+ block_offset += (1024 << sblock_dev->block_size) * 8 * sizeof(sblock_dev->block_map);
+ block_offset += sizeof(siska_sblock_dev_t);
+
+ ret = dev->fops->lseek(dir, block_offset, SISKA_SEEK_SET);
+ if (ret != block_offset) {
+ siska_printk("fs sblock seek error");
+ goto _error;
+ }
+ }
+
+ *pfs = fs;
+ return 0;
+
+_error:
+ while (fs->sblock) {
+ sblock = fs->sblock;
+ fs->sblock = sblock->next;
+
+ siska_sblock_free(sblock);
+ }
+_close_dev:
+ if (dev->fops->close)
+ dev->fops->close(dir);
+ dir->dev = NULL;
+_open_dev:
+ siska_kfree(fs);
+ return -1;
+}
+
+int siska0_umount(siska_file_t* dir)
+{
+ return 0;
+}
+
+siska_vfs_t siska_fs_siska0 =
+{
+ .name = "siska0",
+
+ .next = NULL,
+
+ .mkfs = siska0_mkfs,
+
+ .mount = siska0_mount,
+ .umount = siska0_umount,
+};
+
--- /dev/null
+#ifndef SISKA_LIST_H
+#define SISKA_LIST_H
+
+#include"siska_def.h"
+
+typedef struct siska_list_s siska_list_t;
+
+struct siska_list_s {
+ struct siska_list_s* prev;
+ struct siska_list_s* next;
+};
+
+static inline void siska_list_init(siska_list_t* h)
+{
+ h->prev = h;
+ h->next = h;
+}
+
+static inline void siska_list_del(siska_list_t* n)
+{
+ n->prev->next = n->next;
+ n->next->prev = n->prev;
+
+ // only to avoid some wrong operations for these 2 invalid pointers
+ n->prev = NULL;
+ n->next = NULL;
+}
+
+static inline void siska_list_add_tail(siska_list_t* h, siska_list_t* n)
+{
+ h->prev->next = n;
+ n->prev = h->prev;
+ n->next = h;
+ h->prev = n;
+}
+
+static inline void siska_list_add_front(siska_list_t* h, siska_list_t* n)
+{
+ h->next->prev = n;
+ n->next = h->next;
+ n->prev = h;
+ h->next = n;
+}
+
+#define SISKA_LIST_INIT(h) {&h, &h}
+
+#define siska_offsetof(type, member) ((char*) &((type*)0)->member)
+
+#define siska_list_data(l, type, member) ((type*)((char*)l - siska_offsetof(type, member)))
+
+#define siska_list_head(h) ((h)->next)
+#define siska_list_tail(h) ((h)->prev)
+#define siska_list_sentinel(h) (h)
+#define siska_list_next(l) ((l)->next)
+#define siska_list_prev(l) ((l)->prev)
+#define siska_list_empty(h) ((h)->next == (h))
+
+#define siska_list_clear(h, type, member, type_free) \
+ do {\
+ siska_list_t* l;\
+ for (l = siska_list_head(h); l != siska_list_sentinel(h);) {\
+ type* t = siska_list_data(l, type, member);\
+ l = siska_list_next(l);\
+ siska_list_del(&t->member);\
+ type_free(t);\
+ t = NULL;\
+ }\
+ } while(0)
+
+#endif
+
--- /dev/null
+#if 0
+#include<stdio.h>
+#include<stdlib.h>
+#include<string.h>
+#endif
+
+#include"siska_mm.h"
+#include"siska_task.h"
+
+#define SISKA_KERNEL_SIZE (128 * 1024)
+
+#define SISKA_MM_EXT_PTR 0x90002
+#define SISKA_MM_EXT_KB (*(volatile unsigned short*)SISKA_MM_EXT_PTR)
+//#define SISKA_MM_EXT_KB (4 * 4)
+#define SISKA_MM_EXT_MAX_KB (15 * 1024)
+
+siska_page_t* siska_pages = (siska_page_t*)(1UL << 20);
+unsigned long siska_total_pages = 0;
+unsigned long siska_used_pages = 0;
+
+#define BLOCK_SHIFT_MIN 5
+static siska_block_head_t siska_block_heads[PG_SHIFT];
+
+static unsigned long base = 0;
+
+static inline int siska_block_is_used(siska_block_t* b)
+{
+ return b->size_used & 0x1;
+}
+
+static inline void siska_block_set_used(siska_block_t* b)
+{
+ b->size_used |= 0x1;
+}
+
+static inline long siska_block_get_shift(long size)
+{
+ long n;
+ asm volatile(
+ "bsr %1, %0"
+ :"=r"(n)
+ :"r"(size)
+ :
+ );
+
+ return n;
+}
+
+static inline siska_block_t* siska_block_head(void* p)
+{
+ return (siska_block_t*)((unsigned long)p - sizeof(long));
+}
+
+static inline void* siska_block_data(siska_block_t* b)
+{
+ return (void*)((unsigned long)b + sizeof(long));
+}
+
+static inline long siska_block_size(siska_block_t* b)
+{
+ long used = b->size_used & 0x1;
+ return used ? b->size_used & ~0x1 : b->size_free;
+}
+
+static inline long siska_block_data_size(siska_block_t* b)
+{
+ long used = b->size_used & 0x1;
+ return used ? (b->size_used & ~0x1) - sizeof(long) : 0;
+}
+
+static inline long siska_block_need_shift(long size)
+{
+ size += sizeof(long);
+ long n;
+ asm volatile(
+ "bsr %1, %0"
+ :"=r"(n)
+ :"r"(size)
+ :
+ );
+
+ n += !!(size & ~(1u << n));
+ return n;
+}
+
+void siska_mm_init()
+{
+ siska_block_head_t* bh;
+
+ unsigned long i;
+ unsigned long mm_ext_KB = SISKA_MM_EXT_KB;
+
+ if (mm_ext_KB > SISKA_MM_EXT_MAX_KB)
+ mm_ext_KB = SISKA_MM_EXT_MAX_KB;
+
+ siska_total_pages = (1024 + mm_ext_KB) >> (PG_SHIFT - 10);
+
+ siska_used_pages = (siska_total_pages * sizeof(siska_page_t) + PG_SIZE - 1) >> PG_SHIFT;
+ siska_used_pages += 1u << 20 >> PG_SHIFT;
+
+// siska_printk("siska_pages: %p, total_pages: %d, used_pages: %d\n", siska_pages, siska_total_pages, siska_used_pages);
+
+ for (i = 0; i < siska_total_pages; i++) {
+
+ siska_spinlock_init(&(siska_pages[i].lock));
+
+ if (i < siska_used_pages)
+ siska_pages[i].refs = 1;
+ else
+ siska_pages[i].refs = 0;
+ }
+
+ for (i = 0; i < PG_SHIFT; i++) {
+ bh = &siska_block_heads[i];
+
+ siska_list_init(&bh->head);
+ siska_spinlock_init(&bh->lock);
+ }
+}
+
+int siska_get_free_pages(siska_page_t** pages, int nb_pages)
+{
+ siska_page_t* pg;
+ siska_page_t* pg2;
+ int i;
+ int j;
+
+ for (i = siska_used_pages; i + nb_pages < siska_total_pages; i += nb_pages) {
+
+ pg = siska_pages + i;
+
+ unsigned long flags;
+ siska_irqsave(flags);
+
+ for (j = 0; j < nb_pages; j++) {
+ pg2 = pg + j;
+
+ siska_spin_lock(&pg2->lock);
+ if (pg2->refs > 0) {
+ siska_spin_unlock(&pg2->lock);
+ break;
+ }
+
+ pg2->refs++;
+ }
+
+ if (j < nb_pages) {
+ for (--j; j >= 0; j--) {
+ pg2 = pg + j;
+ pg2->refs--;
+ siska_spin_unlock(&pg2->lock);
+ }
+ siska_irqrestore(flags);
+
+ } else {
+ for (--j; j >= 0; j--) {
+ pg2 = pg + j;
+ siska_spin_unlock(&pg2->lock);
+ }
+ siska_irqrestore(flags);
+
+ *pages = pg;
+ return nb_pages;
+ }
+ }
+
+ return -1;
+}
+
+int siska_free_pages(siska_page_t* pages, int nb_pages)
+{
+ siska_page_t* pg;
+ int i;
+
+ for (i = 0; i < nb_pages; i++) {
+ pg = pages + i;
+
+ unsigned long flags;
+ siska_spin_lock_irqsave(&pg->lock, flags);
+ pg->refs--;
+ siska_spin_unlock_irqrestore(&pg->lock, flags);
+ }
+ return 0;
+}
+
+void* siska_kmalloc(int size)
+{
+ if (size + sizeof(long) > (PG_SIZE >> 1))
+ return NULL;
+
+ siska_block_head_t* bh;
+ siska_block_t* b;
+ siska_block_t* b2;
+ siska_list_t* l;
+
+ long shift;
+ long i;
+
+ shift = siska_block_need_shift(size);
+
+ shift = shift < BLOCK_SHIFT_MIN ? BLOCK_SHIFT_MIN : shift;
+
+ bh = &siska_block_heads[shift];
+
+ unsigned long flags;
+ siska_spin_lock_irqsave(&bh->lock, flags);
+ if (!siska_list_empty(&bh->head)) {
+
+ l = siska_list_head(&bh->head);
+ b = siska_list_data(l, siska_block_t, list);
+
+ siska_list_del(&b->list);
+ siska_spin_unlock_irqrestore(&bh->lock, flags);
+
+ b->size_used = 1u << shift;
+ siska_block_set_used(b);
+
+ return siska_block_data(b);
+ }
+ siska_spin_unlock_irqrestore(&bh->lock, flags);
+
+ for (i = shift + 1; i < PG_SHIFT; i++) {
+ bh = &siska_block_heads[i];
+
+ siska_spin_lock_irqsave(&bh->lock, flags);
+ if (siska_list_empty(&bh->head)) {
+ siska_spin_unlock_irqrestore(&bh->lock, flags);
+ continue;
+ }
+
+ l = siska_list_head(&bh->head);
+ b = siska_list_data(l, siska_block_t, list);
+
+ siska_list_del(&b->list);
+ siska_spin_unlock_irqrestore(&bh->lock, flags);
+
+ long j;
+ for (j = i - 1; j >= shift; j--) {
+ bh = &siska_block_heads[j];
+
+ b2 = (siska_block_t*)((unsigned long)b + (1u << j));
+ b->size_free = 1u << j;
+
+ siska_spin_lock_irqsave(&bh->lock, flags);
+ siska_list_add_front(&bh->head, &b->list);
+ siska_spin_unlock_irqrestore(&bh->lock, flags);
+ b = b2;
+ }
+
+ b->size_used = 1u << shift;
+ siska_block_set_used(b);
+
+ return siska_block_data(b);
+ }
+
+ siska_page_t* pg = NULL;
+ if (siska_get_free_pages(&pg, 1) < 0)
+ return NULL;
+
+ b = (siska_block_t*) siska_page_addr(pg);
+
+// printf("%s(), %d, b: %p, size: %ld, shift: %ld, pg: %p\n", __func__, __LINE__, b, size, shift, pg);
+
+ for (i = PG_SHIFT - 1; i >= shift; i--) {
+ bh = &siska_block_heads[i];
+
+ b2 = (siska_block_t*)((unsigned long)b + (1u << i));
+
+// printf("%s(), %d, b2: %p, size: %ld, shift: %ld\n", __func__, __LINE__, b2, 1u << i, i);
+ b->size_free = 1u << i;
+
+ siska_spin_lock_irqsave(&bh->lock, flags);
+ siska_list_add_front(&bh->head, &b->list);
+ siska_spin_unlock_irqrestore(&bh->lock, flags);
+ b = b2;
+ }
+
+ b->size_used = 1u << shift;
+ siska_block_set_used(b);
+
+ return siska_block_data(b);
+}
+
+void siska_memset(void* dst, unsigned long data, unsigned long size)
+{
+ asm volatile(
+ "movl %0, %%ecx\n\t"
+ "movl %1, %%edi\n\t"
+ "movl %2, %%eax\n\t"
+ "cld\n\t"
+ "rep stosb\n\t"
+ :
+ :"r"(size), "r"(dst), "r"(data)
+ :"ecx", "edi", "eax"
+ );
+}
+
+void siska_memcpy(void* dst, const void* src, unsigned long size)
+{
+ asm volatile(
+ "movl %0, %%ecx\n\t"
+ "movl %1, %%edi\n\t"
+ "movl %2, %%esi\n\t"
+ "cld\n\t"
+ "rep movsb\n\t"
+ :
+ :"r"(size), "r"(dst), "r"(src)
+ :"ecx", "edi", "esi"
+ );
+}
+
+void* siska_krealloc(void* p, int size)
+{
+ if (size <= 0) {
+ siska_kfree(p);
+ return NULL;
+ }
+
+ if (size + sizeof(long) > (PG_SIZE >> 1))
+ return NULL;
+
+ siska_block_t* b = siska_block_head(p);
+// printf("b: %p\n", b);
+ long old_datasize = siska_block_data_size(b);
+
+ if (old_datasize < size) {
+ void* p2 = siska_kmalloc(size);
+ if (!p2)
+ return NULL;
+
+ siska_memcpy(p2, p, size);
+ siska_kfree(p);
+ return p2;
+
+ } else if (old_datasize == size)
+ return p;
+
+ long old_size = siska_block_size(b);
+ long old_shift = siska_block_get_shift(old_size);
+ long new_shift = siska_block_need_shift(size);
+
+// printf("%s(), %d, b: %p, size: %ld, shift: %ld\n", __func__, __LINE__, b, size, old_shift);
+
+ long i;
+ for (i = old_shift - 1; i >= new_shift; i--) {
+
+ siska_block_head_t* bh;
+ siska_block_t* b2;
+
+ bh = &siska_block_heads[i];
+
+ b2 = (siska_block_t*)((unsigned long)b + (1u << i));
+ b2->size_free = 1u << i;
+
+// printf("%s(), %d, b2: %p, shift i: %ld\n", __func__, __LINE__, b, i);
+
+ unsigned long flags;
+ siska_spin_lock_irqsave(&bh->lock, flags);
+ siska_list_add_front(&bh->head, &b2->list);
+ siska_spin_unlock_irqrestore(&bh->lock, flags);
+ }
+
+ b->size_used = 1u << new_shift;
+ siska_block_set_used(b);
+ return p;
+}
+
+void siska_kfree(void* p)
+{
+ if (!p)
+ return;
+
+ siska_block_head_t* bh;
+ siska_block_t* b;
+ siska_block_t* b2;
+
+ b = siska_block_head(p);
+
+ long size = siska_block_size(b);
+ long shift = siska_block_get_shift(size);
+
+ b->size_free = size;
+// printf("%s(), %d, b: %p, size: %ld, shift: %ld\n", __func__, __LINE__, b, size, shift);
+
+ long i;
+ for (i = shift; i < PG_SHIFT; i++) {
+
+ bh = &siska_block_heads[i];
+
+// printf("%s(), %d, b: %p, size: %ld, shift i: %ld\n", __func__, __LINE__, b, size, i);
+
+ if (!((unsigned long)b & ((size << 1) - 1))) {
+
+ b2 = (siska_block_t*)((unsigned long)b + size);
+
+ unsigned long flags;
+ siska_spin_lock_irqsave(&bh->lock, flags);
+ if (siska_block_is_used(b2)) {
+
+ siska_list_add_front(&bh->head, &b->list);
+ siska_spin_unlock_irqrestore(&bh->lock, flags);
+ return;
+ }
+ siska_list_del(&b2->list);
+ siska_spin_unlock_irqrestore(&bh->lock, flags);
+
+ if (b2->size_free != size) {
+ while (1);
+ }
+
+ size <<= 1;
+ b->size_free = size;
+ continue;
+ }
+
+ b2 = (siska_block_t*)((unsigned long)b - size);
+// printf("%s(), %d, b2: %p, b: %p, size: %ld, i: %ld\n", __func__, __LINE__, b2, b, size, i);
+
+ unsigned long flags;
+ siska_spin_lock_irqsave(&bh->lock, flags);
+ if (siska_block_is_used(b2)) {
+
+ siska_list_add_front(&bh->head, &b->list);
+ siska_spin_unlock_irqrestore(&bh->lock, flags);
+ return;
+ }
+ siska_list_del(&b2->list);
+ siska_spin_unlock_irqrestore(&bh->lock, flags);
+
+ b = b2;
+ size <<= 1;
+ b->size_free = size;
+ }
+// printf("%s(), %d, b: %p, size: %ld, shift i: %ld\n", __func__, __LINE__, b, size, i);
+
+ if (b->size_free != PG_SIZE) {
+ while (1);
+ }
+
+ siska_page_t* pg = siska_addr_page((unsigned long)b);
+
+// printf("%s(), %d, b: %p, size: %ld, pg: %p\n", __func__, __LINE__, b, size, pg);
+
+ siska_free_pages(pg, 1);
+}
+
+void _do_page_fault(unsigned long vaddr, unsigned long error_code, unsigned long CPL)
+{
+ unsigned long* pg_dir;
+ unsigned long* pg_table;
+ unsigned long paddr;
+ unsigned long paddr2;
+ siska_page_t* pg = NULL;
+ siska_page_t* pg2 = NULL;
+
+ pg_dir = (unsigned long*) current->cr3;
+
+ if (!(pg_dir[vaddr >> 22] & PG_FLAG_PRESENT)) {
+
+ if (siska_get_free_pages(&pg, 1) < 0)
+ return;
+
+ paddr = siska_page_addr(pg);
+
+ pg_table = (unsigned long*)paddr;
+
+ pg_dir[vaddr >> 22] = paddr | 0x7;
+
+ siska_memset(pg_table, 0, PG_SIZE);
+ } else {
+ paddr = pg_dir[vaddr >> 22] & ~(PG_SIZE - 1);
+
+ pg = siska_addr_page(paddr);
+
+ unsigned long flags;
+ siska_spin_lock_irqsave(&pg->lock, flags);
+ if (pg->refs > 1) {
+ siska_spin_unlock_irqrestore(&pg->lock, flags);
+
+ if (siska_get_free_pages(&pg2, 1) < 0)
+ return;
+
+ paddr2 = siska_page_addr(pg2);
+ siska_memcpy((void*)paddr2, (void*)paddr, PG_SIZE);
+
+ pg_dir[vaddr >> 22] = paddr2 | 0x7;
+
+ siska_unref_page(pg);
+
+ pg_table = (unsigned long*)paddr2;
+ } else {
+ siska_spin_unlock_irqrestore(&pg->lock, flags);
+
+ pg_dir[vaddr >> 22] = paddr2 | 0x7;
+
+ pg_table = (unsigned long*)paddr;
+
+ int i;
+ for (i = 0; i < 1024; i++)
+ pg_table[i] &= ~PG_FLAG_WRITE;
+ }
+ }
+
+ if (!(error_code & PG_FLAG_PRESENT)) {
+ // page not exist
+
+ if (siska_get_free_pages(&pg, 1) < 0)
+ return;
+
+ paddr = siska_page_addr(pg);
+
+ pg_table[(vaddr >> 12) & 0x3ff] = paddr | 0x7;
+
+ } else if (error_code & PG_FLAG_WRITE) {
+ // page can't write, read only
+
+ paddr = pg_table[(vaddr >> 12) & 0x3ff] & ~(PG_SIZE - 1);
+
+ pg = siska_addr_page(paddr);
+
+ unsigned long flags;
+ siska_spin_lock_irqsave(&pg->lock, flags);
+ if (pg->refs > 1) {
+ siska_spin_unlock_irqrestore(&pg->lock, flags);
+
+ if (siska_get_free_pages(&pg2, 1) < 0)
+ return;
+
+ paddr2 = siska_page_addr(pg2);
+ siska_memcpy((void*)paddr2, (void*)paddr, PG_SIZE);
+
+ pg_table[(vaddr >> 12) & 0x3ff] = paddr2 | 0x7;
+
+ siska_unref_page(pg);
+ } else {
+ siska_spin_unlock_irqrestore(&pg->lock, flags);
+
+ pg_table[(vaddr >> 12) & 0x3ff] = paddr | 0x7;
+ }
+ }
+}
+
+void siska_free_memory(siska_task_t* task)
+{
+ unsigned long* dir = (unsigned long*)task->cr3;
+
+ unsigned long i;
+ unsigned long j;
+ unsigned long paddr;
+ unsigned long vaddr;
+
+ for (i = 0; i < 1024; i++) {
+
+ if (!(dir[i] & PG_FLAG_PRESENT))
+ continue;
+
+ unsigned long* table = (unsigned long*) (dir[i] & ~(PG_SIZE - 1));
+ siska_page_t* pg;
+
+ for (j = 0; j < 1024; j++) {
+
+ if (!(table[j] & PG_FLAG_PRESENT))
+ continue;
+
+ paddr = table[j] & ~(PG_SIZE - 1);
+ vaddr = (i << 22) | (j << 12);
+
+ if (vaddr >= task->code3 & ~(PG_SIZE - 1)
+ && vaddr < task->end3 & ~(PG_SIZE - 1)) {
+ table[j] &= ~PG_FLAG_WRITE;
+
+ pg = siska_addr_page(paddr);
+ siska_free_pages(pg, 1);
+ pg = NULL;
+ }
+ }
+
+ pg = siska_addr_page((unsigned long)table);
+ siska_free_pages(pg, 1);
+ pg = NULL;
+ }
+}
+
+int siska_copy_memory(siska_task_t* child, siska_task_t* parent, unsigned long esp3)
+{
+ unsigned long* child_dir = (unsigned long*)child->cr3;
+ unsigned long* parent_dir = (unsigned long*)parent->cr3;
+
+ unsigned long i;
+ unsigned long j;
+
+ unsigned long vaddr;
+ unsigned long paddr;
+
+ for (i = 0; i < 1024; i++) {
+
+ child_dir[i] = parent_dir[i];
+
+ if (!(parent_dir[i] & PG_FLAG_PRESENT))
+ continue;
+
+ unsigned long* table = (unsigned long*) (parent_dir[i] & ~(PG_SIZE - 1));
+
+ siska_page_t* pg = siska_addr_page((unsigned long)table);
+ siska_ref_page(pg);
+
+ for (j = 0; j < 1024; j++) {
+
+ if (!(table[j] & PG_FLAG_PRESENT))
+ continue;
+
+ paddr = table[j] & ~(PG_SIZE - 1);
+ vaddr = (i << 22) | (j << 12);
+
+ // share user code & data
+ if (vaddr >= parent->code3 & ~(PG_SIZE - 1)
+ && vaddr <= parent->brk3 & ~(PG_SIZE - 1)) {
+ table[j] &= ~PG_FLAG_WRITE;
+
+ pg = siska_addr_page(paddr);
+ siska_ref_page(pg);
+ }
+ }
+ }
+
+ for (vaddr = esp3 & ~(PG_SIZE - 1); vaddr < parent->ebp3; vaddr += PG_SIZE) {
+
+ i = vaddr >> 22;
+ j = (vaddr >> 12) & 0x3ff;
+
+ if (!(parent_dir[i] & PG_FLAG_PRESENT))
+ continue;
+
+ unsigned long* child_table = (unsigned long*) ( child_dir[i] & ~(PG_SIZE - 1));
+ unsigned long* parent_table = (unsigned long*) (parent_dir[i] & ~(PG_SIZE - 1));
+
+ siska_page_t* pg = NULL;
+
+ if (child_table == parent_table) {
+
+ if (siska_get_free_pages(&pg, 1) < 0) {
+ siska_printk("siska_copy_memory, error0\n");
+ goto _error;
+ }
+
+ child_table = (unsigned long*)siska_page_addr(pg);
+ child_dir[i] = (unsigned long )child_table | 0x7;
+
+ siska_memcpy(child_table, parent_table, PG_SIZE);
+
+ pg = siska_addr_page((unsigned long)parent_table);
+ siska_unref_page(pg);
+ pg = NULL;
+ }
+
+ if (!(parent_table[j] & PG_FLAG_PRESENT))
+ continue;
+
+ if (siska_get_free_pages(&pg, 1) < 0) {
+ siska_printk("siska_copy_memory, error1\n");
+ goto _error;
+ }
+
+ unsigned long child_paddr = siska_page_addr(pg);
+ unsigned long parent_paddr = parent_table[j] & ~(PG_SIZE - 1);
+
+ child_table[j] = child_paddr | 0x7;
+
+ siska_memcpy((void*)child_paddr, (void*)parent_paddr, PG_SIZE);
+
+ pg = siska_addr_page(parent_paddr);
+ siska_unref_page(pg);
+ pg = NULL;
+
+ parent_table[j] |= PG_FLAG_WRITE;
+ }
+ return 0;
+
+_error:
+ siska_free_memory(child);
+ return -1;
+}
+
+#if 0
+int main()
+{
+ siska_mm_init();
+
+ void* p0 = siska_kmalloc(5);
+ void* p1 = siska_kmalloc(17);
+
+ printf("p0: %p\n", p0);
+ printf("p1: %p\n", p1);
+
+ void* p2 = siska_kmalloc(37);
+ void* p3 = siska_kmalloc(43);
+
+ printf("p2: %p\n", p2);
+ printf("p3: %p\n", p3);
+
+ char* str = "hello world!";
+ int len = strlen(str);
+ siska_memcpy(p2, str, len + 1);
+ siska_memcpy(p3, str, len + 1);
+
+ void* p4 = siska_krealloc(p3, 47);
+ void* p5 = siska_krealloc(p2, 23);
+
+ printf("p4: %p, %s\n", p4, p4);
+ printf("p5: %p, %s\n", p5, p5);
+ printf("\n");
+
+ printf("p0: %p\n", p0);
+ siska_kfree(p0);
+ printf("\n");
+
+ printf("p1: %p\n", p1);
+ siska_kfree(p1);
+ printf("\n");
+
+ printf("p4: %p\n", p4);
+ siska_kfree(p4);
+ printf("\n");
+
+ printf("p5: %p\n", p5);
+ siska_kfree(p5);
+
+ return 0;
+}
+#endif
--- /dev/null
+#ifndef SISKA_MM_H
+#define SISKA_MM_H
+
+#include"siska_core.h"
+
+struct siska_mm_s
+{
+};
+
+typedef struct {
+ siska_spinlock_t lock;
+
+ int refs;
+} siska_page_t;
+
+typedef struct {
+ union {
+ siska_list_t list;
+ long size_used;
+ };
+ long size_free;
+} siska_block_t;
+
+typedef struct {
+ siska_list_t head;
+ siska_spinlock_t lock;
+} siska_block_head_t;
+
+#define PG_FLAG_PRESENT 0x1
+#define PG_FLAG_WRITE 0x2
+
+extern siska_page_t* siska_pages;
+
+void siska_mm_init();
+
+int siska_get_free_pages(siska_page_t** pages, int nb_pages);
+int siska_free_pages (siska_page_t* pages, int nb_pages);
+
+static inline void siska_ref_page(siska_page_t* pg)
+{
+ if (pg) {
+ unsigned long flags;
+ siska_spin_lock_irqsave(&pg->lock, flags);
+ pg->refs++;
+ siska_spin_unlock_irqrestore(&pg->lock, flags);
+ }
+}
+static inline void siska_unref_page(siska_page_t* pg)
+{
+ if (pg) {
+ unsigned long flags;
+ siska_spin_lock_irqsave(&pg->lock, flags);
+ pg->refs--;
+ siska_spin_unlock_irqrestore(&pg->lock, flags);
+ }
+}
+
+static inline unsigned long siska_page_addr(siska_page_t* page)
+{
+ unsigned long index = (unsigned long)(page - siska_pages);
+ unsigned long addr = index << PG_SHIFT;
+ return addr;
+}
+
+static inline siska_page_t* siska_addr_page(unsigned long addr)
+{
+ return siska_pages + (addr >> PG_SHIFT);
+}
+#ifdef ON_BOCHS
+void* siska_kmalloc(int size);
+void* siska_krealloc(void* p, int size);
+void siska_kfree(void* p);
+
+void siska_memcpy(void* dst, const void* src, unsigned long size);
+void siska_memset(void* dst, unsigned long data, unsigned long size);
+#else
+#include<stdlib.h>
+#include<string.h>
+#define siska_kmalloc malloc
+#define siska_krealloc realloc
+#define siska_kfree free
+#define siska_memcpy memcpy
+#define siska_memset memset
+#endif
+
+int siska_copy_memory(siska_task_t* child, siska_task_t* parent, unsigned long esp3);
+void siska_free_memory(siska_task_t* task);
+
+#endif
+
--- /dev/null
+
+.code32
+.text
+.global _page_fault_int_handler, _do_page_fault
+
+.align 4
+_page_fault_msg:
+.asciz "page fault interrupt!\n"
+
+.align 4
+_page_fault_int_handler:
+#40 cs
+#36 eip
+#32 error_code
+#28 ds
+#24 es
+#20 fs
+#16 gs
+#12 eax
+#8 ebx
+#4 ecx
+#0 edx
+
+ cli
+
+ push %ds
+ push %es
+ push %fs
+ push %gs
+
+ pushl %eax
+ pushl %ebx
+ pushl %ecx
+ pushl %edx
+
+ movl $0x10, %eax
+ mov %ax, %ds
+ mov %ax, %es
+ mov %ax, %fs
+ mov %ax, %gs
+
+ movl 40(%esp), %edx
+ movl 32(%esp), %ecx
+ movl %cr2, %eax
+ sti
+
+ andl $0x3, %edx
+
+ pushl %edx
+ pushl %ecx
+ pushl %eax
+ call _do_page_fault
+ addl $12, %esp
+
+ popl %edx
+ popl %ecx
+ popl %ebx
+ popl %eax
+
+ pop %gs
+ pop %fs
+ pop %es
+ pop %ds
+
+ addl $4, %esp #drop error code
+ iret
+
--- /dev/null
+#include"siska_def.h"
+
+int siska_ulong2a(char* buf, int* pn, int size, unsigned long num)
+{
+ int n = *pn;
+ int i = n;
+
+ while (n < size - 1) {
+
+ buf[n++] = num % 10 + '0';
+
+ num /= 10;
+ if (0 == num)
+ break;
+ }
+
+ *pn = n--;
+
+ while (i < n) {
+ char c = buf[i];
+ buf[i++] = buf[n];
+ buf[n--] = c;
+ }
+ return *pn;
+}
+
+int siska_long2a(char* buf, int* pn, int size, long num)
+{
+ int n = *pn;
+
+ if (n < size - 1 && num < 0) {
+ buf[n++] = '-';
+ num = -num;
+ }
+
+ *pn = n;
+ return siska_ulong2a(buf, pn, size, num);
+}
+
+int siska_double2a(char* buf, int* pn, int size, double num)
+{
+ if (*pn < size - 1 && num < 0.0) {
+ buf[(*pn)++] = '-';
+ num = -num;
+ }
+
+ long l = (long)num;
+ long diff = (long)((num - l) * 1e6);
+
+ siska_ulong2a(buf, pn, size, l);
+
+ if (*pn < size - 1)
+ buf[(*pn)++] = '.';
+
+ return siska_ulong2a(buf, pn, size, diff);
+}
+
+int siska_hex2a(char* buf, int* pn, int size, unsigned long num)
+{
+ int n = *pn;
+ int i = n;
+
+ while (n < size - 1) {
+
+ unsigned char x = num % 16;
+
+ buf[n++] = x > 9 ? x - 10 + 'a' : x + '0';
+
+ num /= 16;
+ if (0 == num)
+ break;
+ }
+
+ *pn = n--;
+
+ while (i < n) {
+ char c = buf[i];
+ buf[i++] = buf[n];
+ buf[n--] = c;
+ }
+ return *pn;
+}
+
+int siska_hex2a_prefix(char* buf, int* pn, int size, unsigned long num)
+{
+ int n = *pn;
+
+ if (n < size - 1 - 2) {
+ buf[n++] = '0';
+ buf[n++] = 'x';
+ }
+
+ *pn = n;
+ return siska_hex2a(buf, pn, size, num);
+}
+
+int siska_p2a(char* buf, int* pn, int size, unsigned long num)
+{
+ if (0 == num) {
+ int n = *pn;
+ char* p = "null";
+
+ while (n < size - 1 && *p)
+ buf[n++] = *p++;
+
+ *pn = n;
+ return n;
+ }
+
+ return siska_hex2a_prefix(buf, pn, size, num);
+}
+
+int siska_str2a(char* buf, int* pn, int size, const char* str)
+{
+ int n = *pn;
+
+ while (n < size - 1 && *str)
+ buf[n++] = *str++;
+
+ *pn = n;
+ return n;
+}
+
+int siska_vsnprintf(char* buf, int size, const char* fmt, siska_va_list ap)
+{
+ int n = 0;
+
+ while (n < size - 1 && *fmt) {
+
+ if ('%' != *fmt) {
+ buf[n++] = *fmt++;
+ continue;
+ }
+
+ fmt++;
+ if ('%' == *fmt) {
+ buf[n++] = *fmt++;
+ continue;
+ }
+
+ int prefix = 0;
+ if ('#' == *fmt) {
+ prefix++;
+ fmt++;
+ }
+
+ int l = 0;
+ if ('l' == *fmt) {
+ l++;
+ fmt++;
+ }
+
+ switch (*fmt) {
+ case 'c':
+ buf[n++] = siska_va_arg(ap, int);
+ break;
+ case 'd':
+ if (l)
+ siska_long2a(buf, &n, size, siska_va_arg(ap, long));
+ else
+ siska_long2a(buf, &n, size, siska_va_arg(ap, int));
+ break;
+ case 'u':
+ if (l)
+ siska_ulong2a(buf, &n, size, siska_va_arg(ap, unsigned long));
+ else
+ siska_ulong2a(buf, &n, size, siska_va_arg(ap, unsigned int));
+ break;
+ case 'x':
+ if (prefix) {
+ if (l)
+ siska_hex2a_prefix(buf, &n, size, siska_va_arg(ap, unsigned long));
+ else
+ siska_hex2a_prefix(buf, &n, size, siska_va_arg(ap, unsigned int));
+ } else {
+ if (l)
+ siska_hex2a(buf, &n, size, siska_va_arg(ap, unsigned long));
+ else
+ siska_hex2a(buf, &n, size, siska_va_arg(ap, unsigned int));
+ }
+ break;
+ case 'p':
+ siska_p2a(buf, &n, size, siska_va_arg(ap, unsigned long));
+ break;
+ case 'f':
+ case 'g':
+ siska_double2a(buf, &n, size, siska_va_arg(ap, double));
+ break;
+ case 's':
+ siska_str2a(buf, &n, size, siska_va_arg(ap, char*));
+ break;
+ default:
+ return -1;
+ break;
+ }
+
+ fmt++;
+ }
+
+ buf[n] = '\0';
+ return n;
+}
+
+int siska_snprintf(char* buf, int size, const char* fmt, ...)
+{
+ siska_va_list ap;
+
+ siska_va_start(ap, fmt);
+ int n = siska_vsnprintf(buf, size, fmt, ap);
+ siska_va_end(ap);
+
+ return n;
+}
+#if 0
+int main()
+{
+ char buf[1024];
+ siska_snprintf(buf, 1023, "i: %d, ld: %ld, x: %x, x: %#lx, p: %p, s: %s, f: %f, d: %lg\n",
+ 100, -255ll, 254, 253, buf, "hello", 2.71828, -3.1415926);
+
+ printf("%s\n", buf);
+ printf("%p\n", buf);
+ return 0;
+}
+#endif
--- /dev/null
+#ifndef SISKA_STRING_H
+#define SISKA_STRING_H
+
+static inline int siska_strcmp(const unsigned char* s0, const unsigned char* s1)
+{
+ while (*s0 && *s1) {
+
+ if (*s0 < *s1)
+ return -1;
+ else if (*s0 > *s1)
+ return 1;
+
+ s0++;
+ s1++;
+ }
+
+ if (*s0 == *s1)
+ return 0;
+
+ return *s0 < *s1 ? -1 : 1;
+}
+
+static inline int siska_strncmp(const unsigned char* s0, const unsigned char* s1, unsigned int n)
+{
+ unsigned int len = 0;
+
+ while (*s0 && *s1 && len < n) {
+
+ if (*s0 < *s1)
+ return -1;
+ else if (*s0 > *s1)
+ return 1;
+
+ s0++;
+ s1++;
+ len++;
+ }
+
+ if (len == n)
+ return 0;
+
+ return *s0 < *s1 ? -1 : 1;
+}
+
+static inline unsigned int siska_strlen(const unsigned char* s)
+{
+ const unsigned char* p = s;
+ while (*p)
+ p++;
+ return (unsigned int)(p - s);
+}
+
+static inline unsigned char* siska_strncpy(unsigned char* dst, const unsigned char* src, unsigned int n)
+{
+ unsigned int len = 0;
+
+ while (*src && len < n) {
+ *dst++ = *src++;
+ len++;
+ }
+
+ if (len < n)
+ *dst = '\0';
+ return dst;
+}
+
+#endif
+
--- /dev/null
+
+.code32
+.text
+.global _timer_int_handler, _syscall_handler, _ret_from_fork, _syscall_table
+.global _jiffies, _do_timer, siska_printk
+.global _fork0_msg, _fork1_msg, _execve_msg
+.global _signal_handler_entry
+
+.align 4
+_timer_msg:
+.asciz "timer interrupt!\n"
+
+.align 4
+_jiffies:
+.long 0
+
+.align 4
+_timer_int_handler:
+#48 old ss
+#44 old esp
+#40 eflags
+#36 cs
+#32 eip
+#28 ds
+#24 es
+#20 fs
+#16 gs
+#12 edx
+#8 ecx
+#4 ebx
+#0 eax
+
+ push %ds
+ push %es
+ push %fs
+ push %gs
+
+ pushl %edx
+ pushl %ecx
+ pushl %ebx
+ pushl %eax
+
+ movl $0x10, %eax
+ mov %ax, %ds
+ mov %ax, %es
+ mov %ax, %fs
+ mov %ax, %gs
+
+ incl _jiffies
+
+ movb $0x20, %al
+ outb %al, $0x20
+
+ movl 36(%esp), %eax
+ testl $0x3, %eax
+ je 1f
+
+ call _do_timer
+
+1:
+_ret_from_syscall:
+ pushl %esp
+ call siska_do_signal
+ popl %esp
+
+ popl %eax
+ popl %ebx
+ popl %ecx
+ popl %edx
+
+ pop %gs
+ pop %fs
+ pop %es
+ pop %ds
+ iret
+
+.align 4
+_signal_handler_entry:
+#24 ret
+#20 sig
+#16 handler
+#12 edx
+#8 ecx
+#4 ebx
+#0 eax
+ pushl %edx
+ pushl %ecx
+ pushl %ebx
+ pushl %eax
+
+ movl 16(%esp), %eax
+ movl 20(%esp), %edx
+
+ pushl %edx
+ call *%eax
+ popl %edx
+
+ popl %eax
+ popl %ebx
+ popl %ecx
+ popl %edx
+ addl $8, %esp
+ ret
+
+.align 4
+_syscall_msg:
+.asciz "syscall interrupt!\n"
+
+.align 4
+_syscall_handler:
+ push %ds
+ push %es
+ push %fs
+ push %gs
+
+ pushl %edx
+ pushl %ecx
+ pushl %ebx
+ pushl %eax
+
+ movl $0x10, %eax
+ mov %ax, %ds
+ mov %ax, %es
+ mov %ax, %fs
+ mov %ax, %gs
+
+ movl (%esp), %eax
+ movl _syscall_table(, %eax, 4), %eax
+
+ pushl %esp
+ call *%eax
+ popl %esp
+
+ movl %eax, (%esp)
+ jmp _ret_from_syscall
+
+_ret_from_fork:
+ movl $0, (%esp)
+ jmp _ret_from_syscall
+
+.align 4
+_syscall_table:
+ .fill 256, 4, 0
+
+_fork0_msg:
+.asciz "fork0 process!\n"
+_fork1_msg:
+.asciz "fork1 process!\n"
+
+_execve_msg:
+.asciz "/home/execve"
+
--- /dev/null
+
+#include"siska_task.h"
+#include"siska_mm.h"
+#include"siska_vfs.h"
+#include"siska_api.h"
+
+#define SISKA_NB_TASKS 16
+
+static siska_task_t* siska_tasks[SISKA_NB_TASKS];
+
+static siska_spinlock_t siska_task_lock;
+
+static siska_list_t siska_task_head;
+
+
+
+void siska_task_init()
+{
+ siska_memset(siska_tasks, 0, sizeof(siska_task_t*) * SISKA_NB_TASKS);
+
+ siska_spinlock_init(&siska_task_lock);
+
+ siska_list_init(&siska_task_head);
+
+ siska_tasks[0] = get_asm_addr(_task0);
+
+ siska_list_add_tail(&siska_task_head, &(siska_tasks[0]->list));
+}
+
+void siska_switch_to(siska_task_t* prev, siska_task_t* next)
+{
+ siska_tss_t* tss = get_asm_addr(_tss0);
+
+ switch_to_pgdir(PGDIR_KERNEL);
+
+ asm volatile(
+ "pushl %%ebp\n\t"
+ "pushfl\n\t"
+ "movl %%esp, %0\n\t"
+ "movl $1f, %1\n\t"
+ "movl %2, %%esp\n\t"
+ "addl $0x1000, %5\n\t"
+ "movl %5, 4(%6)\n\t"
+ "movl %4, %%cr3\n\t"
+ "jmp *%3\n\t"
+ "1:\n\t"
+ "popfl\n\t"
+ "popl %%ebp\n\t"
+ :"=m"(prev->esp0), "=m"(prev->eip)
+ :"r"(next->esp0), "r"(next->eip), "r"(next->cr3), "r"(next), "r"(tss)
+ :"esp", "ebp", "flags"
+ );
+}
+
+void siska_schedule()
+{
+ siska_list_t* l;
+ siska_task_t* next;
+ siska_task_t* parent;
+
+ unsigned long flags;
+ siska_spin_lock_irqsave(&siska_task_lock, flags);
+#if 1
+ for (l = siska_list_head(&siska_task_head);
+ l != siska_list_sentinel(&siska_task_head);
+ l = siska_list_next(l)) {
+
+ next = siska_list_data(l, siska_task_t, list);
+
+// if (SISKA_TASK_SLEEP == next->status)
+// continue;
+
+ if (next != current)
+ break;
+ }
+
+ if (l == siska_list_sentinel(&siska_task_head))
+ next = siska_tasks[0];
+#else
+ siska_list_del(¤t->list);
+ siska_list_add_tail(&siska_task_head, ¤t->list);
+
+ l = siska_list_head(&siska_task_head);
+ next = siska_list_data(l, siska_task_t, list);
+#endif
+#if 0
+ if (next->ppid >= 0) {
+ parent = siska_tasks[next->ppid];
+ if (SISKA_TASK_SLEEP == parent->status)
+ parent->status = SISKA_TASK_RUNNING;
+ }
+#endif
+ siska_spin_unlock_irqrestore(&siska_task_lock, flags);
+
+ if (next == current)
+ return;
+
+ siska_switch_to(current, next);
+}
+
+int siska_fork(siska_regs_t* regs)
+{
+ siska_task_t* child;
+ siska_page_t* pg;
+
+ unsigned long esp = (unsigned long)regs;
+ unsigned long* dir;
+ int cpid = -1;
+ int i;
+
+ pg = NULL;
+ if (siska_get_free_pages(&pg, 2) < 0) {
+ siska_printk("fork error0!\n");
+ return -1;
+ }
+
+ child = (siska_task_t*) siska_page_addr(pg);
+
+ current->status = SISKA_TASK_SLEEP;
+
+ unsigned long flags;
+ siska_spin_lock_irqsave(&siska_task_lock, flags);
+ for (i = 1; i < SISKA_NB_TASKS; i++) {
+ if (!siska_tasks[i]) {
+ cpid = i;
+ siska_tasks[i] = child;
+ break;
+ }
+ }
+ siska_spin_unlock_irqrestore(&siska_task_lock, flags);
+
+ if (-1 == cpid) {
+ siska_free_pages(pg, 2);
+ current->status = SISKA_TASK_RUNNING;
+ siska_printk("fork error1!\n");
+ goto error;
+ }
+
+ siska_memcpy(child, current, PG_SIZE);
+
+ child->cr3 = siska_page_addr(pg + 1);
+
+ if (siska_copy_memory(child, current, regs->esp) < 0) {
+ siska_free_pages(pg, 2);
+ current->status = SISKA_TASK_RUNNING;
+ siska_printk("fork error2!\n");
+ goto error;
+ }
+
+ child->pid = cpid;
+ child->ppid = current->pid;
+ child->eip = (unsigned long)get_asm_addr(_ret_from_fork);
+ child->esp0 = esp;
+ child->status = SISKA_TASK_RUNNING;
+
+ child->signal_flags = 0;
+ siska_memset(child->signal_handlers, (unsigned long)SISKA_SIG_DFL, SISKA_NB_SIGNALS * sizeof(void*));
+
+ siska_spin_lock_irqsave(&siska_task_lock, flags);
+ siska_list_add_front(&siska_task_head, &child->list);
+ siska_spin_unlock_irqrestore(&siska_task_lock, flags);
+
+ siska_printk("fork ok!\n");
+
+ siska_schedule();
+error:
+ return cpid;
+}
+
+int __siska_kill(int pid, int signal)
+{
+// siska_printk("kill, pid: %d, signal: %d\n", pid, signal);
+ if (pid < 0 || pid >= SISKA_NB_TASKS)
+ return -1;
+
+ if (signal < 0 || signal >= SISKA_NB_SIGNALS)
+ return -1;
+
+ if (0 == signal) {
+ if (siska_tasks[pid])
+ return 0;
+ return -1;
+ }
+
+ unsigned long flags;
+ siska_spin_lock_irqsave(&siska_task_lock, flags);
+ if (siska_tasks[pid]) {
+
+ switch_to_pgdir(PGDIR_KERNEL);
+ siska_tasks[pid]->signal_flags |= 1u << signal;
+ switch_to_pgdir(current->cr3);
+
+ if (SISKA_SIGCHLD == signal)
+ siska_printk("kill, pid: %d, siska_tasks[%d]: %p, signal: %d\n", pid, pid, siska_tasks[pid], signal);
+ siska_spin_unlock_irqrestore(&siska_task_lock, flags);
+ return 0;
+ }
+
+ siska_spin_unlock_irqrestore(&siska_task_lock, flags);
+ return -1;
+}
+
+int siska_kill(siska_regs_t* regs)
+{
+ int pid = (int)regs->ebx;
+ int signal = (int)regs->ecx;
+
+ return __siska_kill(pid, signal);
+}
+
+int siska_signal(siska_regs_t* regs)
+{
+ int signal = (int)regs->ebx;
+ void* handler = (void*)regs->ecx;
+
+ if (signal < 0 || signal >= SISKA_NB_SIGNALS)
+ return -1;
+
+ current->signal_handlers[signal] = handler;
+ return 0;
+}
+
+void _signal_handler_default(int sig)
+{
+ int pid = siska_api_syscall(SISKA_SYSCALL_GETPID, 0, 0, 0);
+ if (0 != pid)
+ siska_api_printf("pid %d, received signal %d\n", pid, sig);
+ siska_api_syscall(SISKA_SYSCALL_EXIT, 0, 0, 0);
+}
+
+void _signal_handler_kill(int sig)
+{
+ siska_api_syscall(SISKA_SYSCALL_EXIT, 0, 0, 0);
+}
+
+void __siska_do_signal(siska_regs_t* regs, int sig, void (*handler)(int sig), int count)
+{
+ void* entry = get_asm_addr(_signal_handler_entry);
+
+ if (0 == count) {
+ regs->esp -= sizeof(long);
+
+ *(unsigned long*)regs->esp = regs->eip;
+ }
+
+ *(long* )(regs->esp - 1 * sizeof(long)) = sig;
+ *(void**)(regs->esp - 2 * sizeof(long)) = handler;
+ *(void**)(regs->esp - 3 * sizeof(long)) = entry;
+
+ regs->esp -= 3 * sizeof(long);
+}
+
+int __siska_wait()
+{
+ int i;
+ for (i = 1; i < SISKA_NB_TASKS; i++) {
+
+ siska_task_t* task;
+ siska_page_t* pg;
+ unsigned long flags;
+
+ siska_spin_lock_irqsave(&siska_task_lock, flags);
+ task = siska_tasks[i];
+ if (!task || SISKA_TASK_ZOMBIE != task->status) {
+ siska_spin_unlock_irqrestore(&siska_task_lock, flags);
+ continue;
+ }
+
+ siska_tasks[i] = NULL;
+ siska_spin_unlock_irqrestore(&siska_task_lock, flags);
+
+ siska_printk("wait, parent: %d, child: %d, exit_code: %d\n", current->pid, task->pid, task->exit_code);
+
+ pg = siska_addr_page((unsigned long)task);
+ siska_printk("pg, refs: %d\n", pg->refs);
+ siska_printk("pg + 1, refs: %d\n", (pg + 1)->refs);
+ siska_free_pages(pg, 2);
+
+ siska_printk("pg, refs: %d\n", pg->refs);
+ siska_printk("pg + 1, refs: %d\n", (pg + 1)->refs);
+ pg = NULL;
+ }
+
+ return 0;
+}
+
+int siska_do_signal(siska_regs_t* regs)
+{
+ int i;
+ int count = 0;
+
+ for (i = 1; i < SISKA_NB_SIGNALS; i++) {
+
+ if (!(current->signal_flags & (1u << i)))
+ continue;
+
+ if (SISKA_SIGCHLD == i)
+ siska_printk("do signal, pid: %d, signal: %d\n", current->pid, i);
+
+ current->signal_flags &= ~(1u << i);
+
+ void* handler = current->signal_handlers[i];
+
+ if (SISKA_SIGCHLD == i) {
+ __siska_wait();
+ continue;
+ }
+
+ if (SISKA_SIGKILL == i) {
+ __siska_do_signal(regs, SISKA_SIGKILL, _signal_handler_kill, count);
+ count++;
+ break;
+ }
+
+ if (SISKA_SIG_IGN == handler)
+ continue;
+
+ if (SISKA_SIG_DFL == handler)
+ __siska_do_signal(regs, i, _signal_handler_default, count);
+ else
+ __siska_do_signal(regs, i, handler, count);
+ count++;
+ }
+
+ if (count > 0) {
+ regs->esp += sizeof(long);
+ regs->eip = (unsigned long)get_asm_addr(_signal_handler_entry);
+ }
+
+ return 0;
+}
+
+void siska_exit(siska_regs_t* regs)
+{
+ if (0 == current->pid)
+ return;
+
+ current->exit_code = (int)regs->ebx;
+ current->status = SISKA_TASK_ZOMBIE;
+
+ siska_printk("exit, pid: %d, ppid: %d, code: %d\n", current->pid, current->ppid, current->exit_code);
+#if 1
+ unsigned long flags;
+ siska_spin_lock_irqsave(&siska_task_lock, flags);
+ siska_list_del(¤t->list);
+ __siska_kill(current->ppid, SISKA_SIGCHLD);
+ siska_spin_unlock_irqrestore(&siska_task_lock, flags);
+
+ siska_free_memory(current);
+ siska_schedule();
+#endif
+}
+
+int siska_wait(siska_regs_t* regs)
+{
+ __siska_wait();
+ return 0;
+}
+
+int siska_execve(siska_regs_t* regs)
+{
+ if (0 == current->pid)
+ return -1;
+
+ char* filename = (char*)regs->ebx;
+
+ siska_printk("execve, filename: %s\n", filename);
+
+ siska_file_t* file = NULL;
+
+ int ret = siska_vfs_open(&file, filename,
+ SISKA_FILE_FILE | SISKA_FILE_FLAG_R | SISKA_FILE_FLAG_W,
+ 0777);
+ if (ret < 0) {
+ siska_printk("open %s, ret: %d\n", filename, ret);
+ return -1;
+ }
+
+ ret = siska_vfs_read(file, (char*)0x800000, 1024);
+ if (ret < 0) {
+ siska_printk("read %s error, ret: %d\n", filename, ret);
+ return -1;
+ }
+ siska_printk("read %s, ret: %d\n", filename, ret);
+
+ current->code3 = 0x800000;
+ current->data3 = 0x800000 + ret;
+ current->heap3 = (current->data3 + PG_SIZE - 1) >> PG_SHIFT << PG_SHIFT;
+ current->brk3 = current->heap3;
+
+ current->ebp3 = 0x900000;
+ current->end3 = current->ebp3;
+
+ regs->esp = 0x900000;
+ regs->eip = 0x800000;
+ return 0;
+}
+
+int siska_getpid()
+{
+ return current->pid;
+}
+
+int siska_getppid()
+{
+ return current->ppid;
+}
+
--- /dev/null
+#ifndef SISKA_TASK_H
+#define SISKA_TASK_H
+
+#include"siska_core.h"
+
+typedef struct {
+ unsigned long eax;
+ unsigned long ebx;
+ unsigned long ecx;
+ unsigned long edx;
+
+ unsigned long gs;
+ unsigned long fs;
+ unsigned long es;
+ unsigned long ds;
+
+ unsigned long eip;
+ unsigned long cs;
+ unsigned long eflags;
+ unsigned long esp;
+ unsigned long ss;
+} siska_regs_t;
+
+struct siska_tss_s
+{
+ unsigned long tss_prev;
+
+ unsigned long esp0;
+ unsigned long ss0;
+
+ unsigned long esp1;
+ unsigned long ss1;
+
+ unsigned long esp2;
+ unsigned long ss2;
+
+ unsigned long cr3;
+ unsigned long eip;
+ unsigned long eflags;
+
+ unsigned long eax;
+ unsigned long ecx;
+ unsigned long edx;
+ unsigned long ebx;
+
+ unsigned long esp;
+ unsigned long ebp;
+
+ unsigned long esi;
+ unsigned long edi;
+
+ unsigned long es;
+ unsigned long cs;
+ unsigned long ss;
+ unsigned long ds;
+ unsigned long fs;
+ unsigned long gs;
+
+ unsigned long ldt;
+
+ unsigned long iomap;
+
+ unsigned long ssp;
+};
+
+struct siska_task_s
+{
+ siska_list_t list;
+
+ int pid;
+ int ppid;
+ int exit_code;
+
+#define SISKA_TASK_RUNNING 1
+#define SISKA_TASK_SLEEP 2
+#define SISKA_TASK_ZOMBIE 3
+ int status;
+
+ unsigned long eip;
+
+ unsigned long esp0;
+ unsigned long ss0;
+
+ unsigned long cr3;
+
+ siska_mm_t* mm;
+
+ unsigned long signal_flags;
+ void (*signal_handlers[SISKA_NB_SIGNALS])(int signal);
+
+ unsigned long code3;
+ unsigned long data3;
+ unsigned long heap3;
+ unsigned long brk3;
+
+ unsigned long ebp3;
+ unsigned long end3;
+};
+
+void siska_task_init();
+
+void siska_schedule();
+int siska_fork(siska_regs_t* regs);
+
+void siska_exit(siska_regs_t* regs);
+int siska_wait(siska_regs_t* regs);
+
+int siska_kill(siska_regs_t* regs);
+int siska_signal(siska_regs_t* regs);
+
+int siska_getpid();
+int siska_getppid();
+
+#endif
+
--- /dev/null
+#include"siska_vfs.h"
+#include"siska_mm.h"
+
+static siska_dev_t siska_dev_root;
+static siska_file_t siska_dir_root;
+static siska_spinlock_t siska_spinlock_root;
+
+static siska_vfs_t* siska_vfs_head = NULL;
+static siska_file_ops_t* siska_fops_head = NULL;
+
+#define ROOTFS_OFFSET_PTR (0x90000 + 500)
+#define ROOTFS_SIZE_PTR (0x90000 + 504)
+#define ROOTFS_OFFSET ((*(volatile unsigned long*) ROOTFS_OFFSET_PTR) << 9)
+#define ROOTFS_SIZE ((*(volatile unsigned long*) ROOTFS_SIZE_PTR) << 9)
+
+extern siska_vfs_t siska_fs_siska0;
+
+static siska_vfs_t* siska_vfs_array[] =
+{
+ &siska_fs_siska0,
+ NULL
+};
+
+extern siska_file_ops_t siska_fops_memory_dev;
+extern siska_file_ops_t siska_fops_siska0;
+
+static siska_file_ops_t* siska_fops_array[] =
+{
+ &siska_fops_memory_dev,
+ &siska_fops_siska0,
+ NULL
+};
+
+void siska_vfs_init()
+{
+ siska_file_ops_t* fops;
+ siska_vfs_t* vfs;
+
+ siska_vfs_head = NULL;
+ siska_fops_head = NULL;
+
+ int i;
+ for (i = 0; siska_vfs_array[i]; i++) {
+
+ vfs = siska_vfs_array[i];
+
+ vfs->next = siska_vfs_head;
+ siska_vfs_head = vfs;
+ }
+
+ for (i = 0; siska_fops_array[i]; i++) {
+
+ fops = siska_fops_array[i];
+
+ fops->next = siska_fops_head;
+ siska_fops_head = fops;
+ }
+}
+
+int siska_vfs_mkfs(siska_file_t* devfile, const char* fsname)
+{
+ siska_vfs_t* vfs;
+
+ if (!devfile || !fsname)
+ return -1;
+
+ for (vfs = siska_vfs_head; vfs; vfs = vfs->next) {
+ if (!siska_strcmp(vfs->name, fsname))
+ break;
+ }
+
+ if (!vfs)
+ return -1;
+
+ if (vfs->mkfs)
+ return vfs->mkfs(devfile);
+
+ return -1;
+}
+
+int siska_vfs_mount(siska_file_t* dir, siska_dev_t* dev, const char* fsname)
+{
+ siska_vfs_t* vfs;
+
+ if (!dir || !dev || !fsname)
+ return -1;
+
+ if (dir->fs)
+ return -1;
+
+ for (vfs = siska_vfs_head; vfs; vfs = vfs->next) {
+ if (!siska_strcmp(vfs->name, fsname))
+ break;
+ }
+
+ if (!vfs)
+ return -1;
+
+ if (vfs->mount)
+ return vfs->mount(&dir->fs, dir, dev);
+ return -1;
+}
+
+int siska_vfs_umount(siska_file_t* dir)
+{
+ siska_vfs_t* vfs;
+
+ if (dir && dir->fs) {
+ vfs = dir->fs->vfs;
+
+ if (vfs && vfs->umount) {
+ if (vfs->umount(dir) < 0)
+ return -1;
+ }
+
+ dir->fs = NULL;
+ return 0;
+ }
+
+ return -1;
+}
+
+siska_file_t* siska_dir_find_child(siska_file_t* dir, const char* name, int len)
+{
+ siska_file_t* file;
+ siska_list_t* l;
+
+ for (l = siska_list_head(&dir->childs); l != siska_list_sentinel(&dir->childs);
+ l = siska_list_next(l)) {
+
+ file = siska_list_data(l, siska_file_t, list);
+
+ if (siska_strlen(file->name) != len)
+ continue;
+
+ if (!siska_strncmp(file->name, name, len))
+ return file;
+ }
+ return NULL;
+}
+
+siska_file_t* siska_dir_add_file(siska_file_t* dir, const char* name, int len)
+{
+ siska_file_t* file;
+
+ file = siska_file_alloc();
+ if (!file)
+ return NULL;
+
+ file->name = siska_kmalloc(len + 1);
+ if (!file->name) {
+ siska_file_free(file);
+ return NULL;
+ }
+
+ siska_memcpy(file->name, name, len);
+ file->name[len] = '\0';
+ file->len = len;
+
+ file->parent = dir;
+
+ siska_list_add_tail(&dir->childs, &file->list);
+
+ return file;
+}
+
+int siska_vfs_open(siska_file_t** pfile, const char* path, int flags, int mode)
+{
+ if (!pfile || !path)
+ return -1;
+
+ char* p0 = (char*)path;
+ char* p1 = p0;
+
+ if ('.' == *p1)
+ return -1;
+
+ if ('/' != *p1)
+ return -1;
+
+ siska_file_t* sentinel;
+ siska_file_t* file;
+ siska_file_t* dir;
+
+ dir = &siska_dir_root;
+ sentinel = NULL;
+
+ p0++;
+ p1 = p0;
+
+ unsigned long eflags;
+ siska_spin_lock_irqsave(&siska_spinlock_root, eflags);
+ while (*p1) {
+ p1++;
+
+ if ('/' != *p1)
+ continue;
+
+ file = siska_dir_find_child(dir, p0, (int)(p1 - p0));
+
+ if (!file) {
+ file = siska_dir_add_file(dir, p0, (int)(p1 - p0));
+ if (!file)
+ goto _error;
+
+ if (!sentinel) {
+ sentinel = dir;
+// siska_printk("sentinel: %s, type: %d, file: %s\n",
+// sentinel->name, siska_file_get_type(sentinel), file->name);
+ }
+
+ siska_file_set_type(file, SISKA_FILE_DIR);
+
+ } else if (SISKA_FILE_DIR != siska_file_type(file)) {
+ siska_printk("file: %s, already exist\n", file->name);
+
+ siska_spin_unlock_irqrestore(&siska_spinlock_root, eflags);
+ return -1;
+ }
+
+ dir = file;
+
+ p1++;
+ while (*p1 && '/' == *p1)
+ p1++;
+ p0 = p1;
+ }
+
+ if ('/' != *p0) {
+
+ file = siska_dir_find_child(dir, p0, (int)(p1 - p0));
+
+ if (!file) {
+ file = siska_dir_add_file(dir, p0, (int)(p1 - p0));
+ if (!file)
+ goto _error;
+
+ if (!sentinel)
+ sentinel = dir;
+
+ siska_file_set_type(file, siska_file_type_of_flags(flags));
+// siska_printk("file: %s, type: %d\n", file->name, siska_file_get_type(file));
+// siska_printk("file: %s, type: %d\n", file->name, siska_file_get_type(file));
+
+ } else if (siska_file_type(file) == siska_file_type_of_flags(flags)) {
+ siska_printk("file: %s, already exist\n", file->name);
+
+ siska_spin_unlock_irqrestore(&siska_spinlock_root, eflags);
+ return -1;
+ }
+ }
+
+ if (!file->ops) {
+
+ siska_file_t* f;
+
+ for (f = file; f; f = f->parent) {
+ if (f->fs) {
+ file->ops = f->fs->fops;
+ break;
+ }
+ }
+
+ if (!file->ops) {
+ siska_printk("file: %s, ops not found\n", file->name);
+
+ dir = file;
+ goto _error;
+ }
+
+ if (file->ops->open) {
+ unsigned int fflags;
+ int ret;
+
+ fflags = file->flags;
+
+ siska_spin_lock(&file->lock);
+ ret = file->ops->open(file, flags, mode);
+ siska_spin_unlock(&file->lock);
+
+ file->flags = fflags;
+
+ if (ret < 0) {
+ siska_printk("file: %s, ops->open() error\n", file->name);
+
+ dir = file;
+ goto _error;
+ }
+ }
+ }
+ siska_spin_unlock_irqrestore(&siska_spinlock_root, eflags);
+
+ *pfile = file;
+ return 0;
+
+_error:
+ if (!sentinel) {
+ siska_spin_unlock_irqrestore(&siska_spinlock_root, eflags);
+ return -1;
+ }
+
+// siska_printk("delete sentinel file: %s, type: %d\n", sentinel->name, siska_file_get_type(sentinel));
+
+ while (dir != sentinel) {
+
+ if (!siska_list_empty(&dir->childs)) {
+ siska_spin_unlock_irqrestore(&siska_spinlock_root, eflags);
+ return -1;
+ }
+
+ siska_file_t* tmp = dir->parent;
+
+// siska_printk("delete new file: %s, type: %d\n", dir->name, siska_file_get_type(dir));
+
+ siska_list_del(&dir->list);
+ siska_file_free(dir);
+ dir = tmp;
+ }
+
+ siska_spin_unlock_irqrestore(&siska_spinlock_root, eflags);
+ return -1;
+}
+
+int siska_vfs_write(siska_file_t* file, const char* buf, int count)
+{
+ if (!file || !buf || count < 0)
+ return -1;
+
+ if (0 == count)
+ return 0;
+
+ unsigned long flags;
+ int ret = -1;
+
+ siska_spin_lock_irqsave(&file->lock, flags);
+ if (file->ops && file->ops->write)
+ ret = file->ops->write(file, buf, count);
+ siska_spin_unlock_irqrestore(&file->lock, flags);
+
+ if (ret < 0)
+ siska_printk("write file: %s, file->ops: %p\n", file->name, file->ops);
+
+ return ret;
+}
+
+int siska_vfs_read(siska_file_t* file, char* buf, int count)
+{
+ if (!file || !buf || count < 0)
+ return -1;
+
+ if (0 == count)
+ return 0;
+
+ unsigned long flags;
+ int ret = -1;
+
+ siska_spin_lock_irqsave(&file->lock, flags);
+ if (file->ops && file->ops->read)
+ ret = file->ops->read(file, buf, count);
+ siska_spin_unlock_irqrestore(&file->lock, flags);
+
+ if (ret < 0)
+ siska_printk("read file: %s, file->ops: %p\n", file->name, file->ops);
+
+ return ret;
+}
+
+int siska_vfs_lseek(siska_file_t* file, long offset, int whence)
+{
+ if (!file)
+ return -1;
+
+ unsigned long flags;
+ int ret = -1;
+
+ siska_spin_lock_irqsave(&file->lock, flags);
+ if (file->ops && file->ops->lseek)
+ ret = file->ops->lseek(file, offset, whence);
+ siska_spin_unlock_irqrestore(&file->lock, flags);
+
+ if (ret < 0)
+ siska_printk("lseek file: %s, file->ops: %p\n", file->name, file->ops);
+
+ return ret;
+}
+
+void siska_dir_print(siska_file_t* dir)
+{
+ siska_file_t* file;
+ siska_list_t* l;
+
+ if (!dir)
+ return;
+
+ if (siska_list_empty(&dir->childs))
+ siska_printk("%s\n", dir->name);
+ else
+ siska_printk("%s/\n", dir->name);
+
+ for (l = siska_list_head(&dir->childs); l != siska_list_sentinel(&dir->childs);
+ l = siska_list_next(l)) {
+
+ file = siska_list_data(l, siska_file_t, list);
+
+ siska_printk("%s/%s\n", dir->name, file->name);
+ }
+}
+
+void siska_dir_print_recursive(siska_file_t* dir, siska_file_t* root)
+{
+ siska_file_t* file;
+ siska_list_t* l;
+
+ if (!dir)
+ return;
+
+ int n = 0;
+ file = dir;
+ while (file != root) {
+ file = file->parent;
+ n++;
+ }
+
+ siska_file_t** path = siska_kmalloc(sizeof(siska_file_t*) * n);
+ if (!path)
+ return;
+
+ n = 0;
+ file = dir;
+ while (file != root) {
+ path[n++] = file;
+ file = file->parent;
+ }
+
+ if (root && root != dir) {
+ if ('/' == root->name[0])
+ siska_printk("/");
+ else
+ siska_printk("./%s/", root->name);
+ }
+
+ while (--n > 0)
+ siska_printk("%s/", path[n]->name);
+
+ siska_printk("%s\n", dir->name);
+ siska_kfree(path);
+ path = NULL;
+
+ for (l = siska_list_head(&dir->childs); l != siska_list_sentinel(&dir->childs);
+ l = siska_list_next(l)) {
+
+ file = siska_list_data(l, siska_file_t, list);
+
+ siska_dir_print_recursive(file, root);
+ }
+}
+
+siska_file_t* siska_file_alloc()
+{
+ siska_file_t* file = siska_kmalloc(sizeof(siska_file_t));
+ if (!file)
+ return NULL;
+
+ siska_list_init(&file->list);
+ siska_list_init(&file->childs);
+ file->parent = NULL;
+
+ file->name = NULL;
+ file->len = 0;
+
+ file->flags = 0;
+ file->mode = 0;
+
+ siska_spinlock_init(&file->lock);
+
+ file->data = NULL;
+ file->size = 0;
+ file->offset = 0;
+
+ file->ops = NULL;
+ file->inode = NULL;
+ file->dev = NULL;
+ file->fs = NULL;
+
+ return file;
+}
+
+void siska_file_free(siska_file_t* file)
+{
+ if (file)
+ siska_kfree(file);
+}
+
+siska_sblock_t* siska_sblock_alloc()
+{
+ siska_sblock_t* sblock = siska_kmalloc(sizeof(siska_sblock_t));
+ if (!sblock)
+ return NULL;
+
+ sblock->next = NULL;
+ sblock->number = 0;
+ sblock->inodes = NULL;
+ sblock->sblock_dev = NULL;
+
+ return sblock;
+}
+
+void siska_sblock_free(siska_sblock_t* sblock)
+{
+ if (sblock) {
+
+ if (sblock->sblock_dev)
+ siska_kfree(sblock->sblock_dev);
+
+ siska_kfree(sblock);
+ }
+}
+
+siska_inode_t* siska_inode_alloc()
+{
+ siska_inode_t* inode = siska_kmalloc(sizeof(siska_inode_t));
+ if (!inode)
+ return NULL;
+
+ inode->next = NULL;
+ inode->file = NULL;
+ inode->sblock = NULL;
+ inode->index = 0;
+ inode->inode_dev = NULL;
+
+ return inode;
+}
+
+void siska_inode_free(siska_inode_t* inode)
+{
+ if (inode) {
+
+ if (inode->inode_dev)
+ siska_kfree(inode->inode_dev);
+
+ siska_kfree(inode);
+ }
+}
+#ifndef ON_BOCHS
+#include<sys/types.h>
+#include<sys/stat.h>
+#include<sys/mman.h>
+#include<fcntl.h>
+#include<unistd.h>
+#endif
+
+int siska_fs_init()
+{
+ siska_vfs_init();
+
+ siska_spinlock_init(&siska_spinlock_root);
+
+ siska_dev_root.name ="rootdev";
+ siska_dev_root.fops = &siska_fops_memory_dev;
+#ifdef ON_BOCHS
+ siska_dev_root.priv = (void*)ROOTFS_OFFSET;
+ siska_dev_root.priv_size = ROOTFS_SIZE;
+#else
+#if 0
+ siska_dev_root.priv = malloc(1024 * 10);
+ siska_dev_root.priv_size = 1024 * 10;
+#else
+ int fd = open("fs.bin", O_RDONLY, 0666);
+ if (fd < 0)
+ return -1;
+
+ siska_dev_root.priv = mmap(NULL, 1024 * 10, PROT_READ , MAP_PRIVATE, fd, 0);
+ if (MAP_FAILED == siska_dev_root.priv)
+ return -1;
+ siska_dev_root.priv_size = 1024 * 10;
+#endif
+#endif
+ siska_dev_root.priv_pos = 0;
+
+ siska_list_init(&siska_dir_root.list);
+ siska_list_init(&siska_dir_root.childs);
+
+ siska_dir_root.parent = NULL;
+
+ siska_dir_root.name = "/";
+ siska_dir_root.len = 1;
+ siska_dir_root.flags = SISKA_FILE_FLAG_R | SISKA_FILE_FLAG_W;
+
+ siska_file_set_type(&siska_dir_root, SISKA_FILE_DIR);
+
+ siska_dir_root.mode = SISKA_FILE_MOD_R | SISKA_FILE_MOD_W | SISKA_FILE_MOD_X;
+
+ siska_dir_root.data = NULL;
+ siska_dir_root.size = 0;
+ siska_dir_root.offset = 0;
+
+ siska_dir_root.ops = NULL;
+ siska_dir_root.inode = NULL;
+ siska_dir_root.dev = &siska_dev_root;
+ siska_dir_root.fs = NULL;
+#if 0
+ if (siska_vfs_mkfs(&siska_dir_root, "siska0") < 0) {
+ printf("%s(),%d\n", __func__, __LINE__);
+ return -1;
+ }
+#endif
+ int ret = siska_vfs_mount(&siska_dir_root, &siska_dev_root, "siska0");
+ siska_printk("root fs init, ret: %d\n", ret);
+ return ret;
+}
+
+#ifndef ON_BOCHS
+static int make_file(siska_file_t** pfile, const char* fname, const char* data, int len)
+{
+ siska_file_t* file = NULL;
+
+ int ret = siska_vfs_open(&file, fname,
+ SISKA_FILE_FILE | SISKA_FILE_FLAG_R | SISKA_FILE_FLAG_W,
+ 0777);
+ if (ret < 0) {
+ printf("%s(),%d, error\n", __func__, __LINE__);
+ return -1;
+ }
+
+ if (data && len > 0) {
+ ret = siska_vfs_write(file, data, len);
+ if (ret < 0) {
+ printf("%s(),%d, ret: %d\n", __func__, __LINE__, ret);
+ return -1;
+ }
+ printf("%s(),%d, ret: %d\n", __func__, __LINE__, ret);
+ }
+
+ *pfile = file;
+ return 0;
+}
+
+static int read_file(siska_file_t* file)
+{
+ unsigned char buf[128] = {0};
+
+ int ret = siska_vfs_lseek(file, 0, SISKA_SEEK_SET);
+ if (ret < 0) {
+ printf("%s(),%d, ret: %d\n", __func__, __LINE__, ret);
+ return -1;
+ }
+
+ ret = siska_vfs_read(file, buf, sizeof(buf) - 1);
+ if (ret < 0) {
+ printf("%s(),%d, ret: %d\n", __func__, __LINE__, ret);
+ return -1;
+ }
+ printf("%s(),%d, ret: %d\n", __func__, __LINE__, ret);
+ printf("%s(),%d, buf: %s\n", __func__, __LINE__, buf);
+
+ printf("%s(),%d, binary:\n", __func__, __LINE__);
+
+ int i;
+ for (i = 0; i < ret; i++)
+ printf("%#x ", buf[i]);
+ printf("\n");
+ return 0;
+}
+
+int main()
+{
+ int ret = siska_fs_init();
+ if (ret < 0) {
+ printf("%s(),%d, error\n", __func__, __LINE__);
+ return -1;
+ }
+
+ siska_file_t* file = NULL;
+ siska_file_t* file2 = NULL;
+#if 0
+ if (make_file(&file, "/home/my", "hello", 6) < 0) {
+ printf("%s(),%d, error\n", __func__, __LINE__);
+ return -1;
+ }
+ printf("\n");
+
+ int fd_exec = open("./execve.bin", O_RDONLY);
+ if (fd_exec < 0) {
+ printf("%s(),%d, error\n", __func__, __LINE__);
+ return -1;
+ }
+
+ char buf[256];
+ ret = read(fd_exec, buf, 256);
+ if (ret < 0) {
+ printf("%s(),%d, error\n", __func__, __LINE__);
+ return -1;
+ }
+ printf("%s(),%d, ret: %d\n", __func__, __LINE__, ret);
+
+ if (make_file(&file2, "/home/execve", buf, ret) < 0) {
+ printf("%s(),%d, error\n", __func__, __LINE__);
+ return -1;
+ }
+#else
+#if 1
+ if (make_file(&file, "/home/my", NULL, 0) < 0) {
+ printf("%s(),%d, error\n", __func__, __LINE__);
+ return -1;
+ }
+#endif
+ if (make_file(&file2, "/home/execve", NULL, 0) < 0) {
+ printf("%s(),%d, error\n", __func__, __LINE__);
+ return -1;
+ }
+#endif
+ printf("\n");
+ siska_dir_print_recursive(&siska_dir_root, &siska_dir_root);
+
+ read_file(file);
+ read_file(file2);
+#if 0
+ int fd = open("fs.bin", O_RDWR | O_CREAT | O_TRUNC, 0666);
+ if (fd > 0) {
+ ret = write(fd, siska_dev_root.priv, siska_dev_root.priv_size);
+ }
+#endif
+ return 0;
+}
+#endif
--- /dev/null
+#ifndef SISKA_VFS_H
+#define SISKA_VFS_H
+
+#include"siska_core.h"
+
+struct siska_file_s
+{
+ siska_list_t list;
+
+ siska_list_t childs;
+ siska_file_t* parent;
+
+ char* name;
+ int len;
+
+#define SISKA_FILE_MOD_X 1u
+#define SISKA_FILE_MOD_W (1u << 1)
+#define SISKA_FILE_MOD_R (1u << 2)
+
+#define SISKA_FILE_FLAG_R (1u)
+#define SISKA_FILE_FLAG_W (1u << 1)
+#define SISKA_FILE_FLAG_NONBLOCK (1u << 2)
+
+#define SISKA_FILE_DIR (1u << 24)
+#define SISKA_FILE_FILE (2u << 24)
+#define SISKA_FILE_DEV (3u << 24)
+#define SISKA_FILE_SOCK (4u << 24)
+
+#define SISKA_SEEK_SET 0
+#define SISKA_SEEK_CUR 1
+#define SISKA_SEEK_END 2
+
+#define siska_file_type_of_flags(flags) (flags & ~0xffffff)
+
+ unsigned int flags;
+ unsigned int mode;
+
+ siska_spinlock_t lock;
+
+ unsigned char* data;
+ long size;
+ long offset;
+
+ siska_file_ops_t* ops;
+
+ siska_inode_t* inode;
+ siska_dev_t* dev;
+
+ siska_fs_t* fs;
+};
+
+struct siska_dev_s
+{
+ char* name;
+
+ void* priv;
+ int priv_size;
+ int priv_pos;
+
+ siska_file_ops_t* fops;
+};
+
+struct siska_file_ops_s
+{
+ const char* type;
+
+ siska_file_ops_t* next;
+
+ int (*open )(siska_file_t* file, int flags, unsigned int mode);
+ int (*close)(siska_file_t* file);
+
+ int (*read )(siska_file_t* file, void* buf, int size);
+ int (*write)(siska_file_t* file, const void* buf, int size);
+
+ int (*lseek)(siska_file_t* file, long offset, int whence);
+ int (*sync )(siska_file_t* file);
+
+ int (*ioctl)(siska_file_t* file, unsigned long cmd, ...);
+};
+
+struct siska_vfs_s
+{
+ const char* name;
+
+ siska_vfs_t* next;
+
+ int (*mkfs) (siska_file_t* devfile);
+
+ int (*mount) (siska_fs_t** pfs, siska_file_t* dir, siska_dev_t* dev);
+ int (*umount)(siska_file_t* dir);
+};
+
+struct siska_fs_s
+{
+ siska_file_t* dir;
+ siska_dev_t* dev;
+ siska_vfs_t* vfs;
+
+ siska_file_ops_t* fops;
+
+ siska_sblock_t* sblock;
+};
+
+struct siska_sblock_s
+{
+ siska_sblock_t* next;
+ unsigned long number;
+
+ siska_inode_t* inodes;
+
+ siska_sblock_dev_t* sblock_dev;
+};
+
+struct siska_inode_s
+{
+ siska_inode_t* next;
+
+ siska_file_t* file;
+
+ siska_sblock_t* sblock;
+ unsigned long index;
+
+ siska_inode_dev_t* inode_dev;
+};
+
+siska_file_t* siska_file_alloc();
+void siska_file_free(siska_file_t* file);
+
+siska_sblock_t* siska_sblock_alloc();
+siska_inode_t* siska_inode_alloc();
+
+void siska_sblock_free(siska_sblock_t* sblock);
+void siska_inode_free(siska_inode_t* inode);
+
+void siska_vfs_init();
+
+int siska_vfs_mkfs (siska_file_t* devfile, const char* fsname);
+
+int siska_vfs_mount (siska_file_t* dir, siska_dev_t* dev, const char* fsname);
+int siska_vfs_umount(siska_file_t* dir);
+
+int siska_vfs_open (siska_file_t** pfile, const char* path, int flags, int mode);
+int siska_vfs_write(siska_file_t* file, const char* buf, int count);
+
+int siska_vfs_read (siska_file_t* file, char* buf, int count);
+int siska_vfs_lseek(siska_file_t* file, long offset, int whence);
+
+void siska_dir_print(siska_file_t* dir);
+void siska_dir_print_recursive(siska_file_t* dir, siska_file_t* root);
+
+int siska_fs_init();
+
+static inline unsigned int siska_file_type(siska_file_t* file)
+{
+ return file->flags & ~0xffffff;
+}
+static inline unsigned int siska_file_get_type(siska_file_t* file)
+{
+ return (file->flags >> 24) & 0xff;
+}
+static inline void siska_file_set_type(siska_file_t* file, unsigned int type)
+{
+ file->flags = (file->flags & 0xffffff) | type;
+}
+
+static inline siska_fs_t* siska_vfs_find_fs(siska_file_t* file)
+{
+ siska_file_t* p;
+
+ for (p = file; p; p = p->parent) {
+
+ if (p->fs)
+ return p->fs;
+ }
+ return NULL;
+}
+
+#endif
+
--- /dev/null
+#include<stdio.h>
+#include"siska_string.h"
+
+int main()
+{
+ char* s0 = "hello world\n";
+ char* s1 = "hello world\n";
+ char* s2 = "hello\n";
+ char* s3 = "hello";
+
+ char buf[8];
+
+ printf("strcmp(s0, s1): %d\n", siska_strcmp(s0, s1));
+ printf("strcmp(s0, s2): %d\n", siska_strcmp(s0, s2));
+ printf("strcmp(s0, s2, 5): %d\n", siska_strncmp(s0, s2, 5));
+ printf("strcmp(s0, s2, 6): %d\n", siska_strncmp(s0, s2, 6));
+
+ printf("strlen(s2): %d\n", siska_strlen(s2));
+ printf("strlen(s3): %d\n", siska_strlen(s3));
+
+ char* p = siska_strncpy(buf, s3, 8);
+ printf("buf: %s, p - buf: %d\n", buf, (int)(p - buf));
+
+ p = siska_strncpy(buf, s3, 4);
+ buf[p - buf] = '\0';
+ printf("buf: %s, p - buf: %d\n", buf, (int)(p - buf));
+}