From 5a9b7d78ee56b682c8ab539295005ee658f7487a Mon Sep 17 00:00:00 2001 From: Jean-Yves Lamoureux Date: Sun, 20 Dec 2009 13:33:11 +0000 Subject: [PATCH] * Total kernel rewrite --- configure.ac | 2 +- kernel/boot/bootsect.asm | 123 ++++++++ kernel/boot/gdt.c | 101 ++++++ kernel/boot/idt.c | 132 ++++++++ kernel/boot/int.asm | 147 +++++++++ kernel/boot/interruptions.c | 112 +++++++ kernel/boot/pic.c | 73 +++++ kernel/boot/stage2.c | 30 ++ kernel/boot/stage2.h | 1 + kernel/drivers/floppy.c | 56 ++++ kernel/drivers/floppy.h | 14 + kernel/drivers/keyboard.c | 101 ++++++ kernel/drivers/memory.c | 4 + kernel/drivers/memory.h | 0 kernel/drivers/processor.c | 50 +++ kernel/drivers/processor.h | 81 +++++ kernel/drivers/timer.c | 42 +++ kernel/drivers/timer.h | 2 + kernel/kernel.c | 421 +++---------------------- kernel/kernel.h | 118 +------ kernel/klibc.c | 598 ++++++++++++++++++++++++++++++++++++ kernel/klibc.h | 125 ++++++++ kernel/multiboot.S | 73 ----- 23 files changed, 1850 insertions(+), 556 deletions(-) create mode 100644 kernel/boot/bootsect.asm create mode 100644 kernel/boot/gdt.c create mode 100644 kernel/boot/idt.c create mode 100644 kernel/boot/int.asm create mode 100644 kernel/boot/interruptions.c create mode 100644 kernel/boot/pic.c create mode 100644 kernel/boot/stage2.c create mode 100644 kernel/boot/stage2.h create mode 100644 kernel/drivers/floppy.c create mode 100644 kernel/drivers/floppy.h create mode 100644 kernel/drivers/keyboard.c create mode 100644 kernel/drivers/memory.c create mode 100644 kernel/drivers/memory.h create mode 100644 kernel/drivers/processor.c create mode 100644 kernel/drivers/processor.h create mode 100644 kernel/drivers/timer.c create mode 100644 kernel/drivers/timer.h create mode 100644 kernel/klibc.c create mode 100755 kernel/klibc.h delete mode 100644 kernel/multiboot.S diff --git a/configure.ac b/configure.ac index 59cfdd2..e5a67b5 100644 --- a/configure.ac +++ b/configure.ac @@ -308,7 +308,7 @@ fi if test "${enable_vga}" = "yes"; then ac_cv_my_have_vga="yes" - CPPFLAGS="${CPPFLAGS} -I. -D__KERNEL__ -nostdinc -include kernel/kernel.h -fno-stack-protector" + CPPFLAGS="${CPPFLAGS} -I. -D__KERNEL__ -nostdinc -include kernel/klibc.h -fno-stack-protector" CFLAGS="${CFLAGS} -fno-builtin -O2 -Wall -fno-stack-protector" CCASFLAGS="${CCASFLAGS} -I. -fno-stack-protector" LDFLAGS="${LDFLAGS} -nostdlib -Wl,-N -Wl,-Ttext -Wl,100000 -fno-stack-protector" diff --git a/kernel/boot/bootsect.asm b/kernel/boot/bootsect.asm new file mode 100644 index 0000000..d55955a --- /dev/null +++ b/kernel/boot/bootsect.asm @@ -0,0 +1,123 @@ +; Boot sector, freely inspired by http://jojo.ouvaton.org/dossiers/boot_sector/tutorial02.html +; Sets a GDT and protected mode +; Copy the kernel (or stage2) to 0x1000 (linear) +; Max kernel size is 25600 bytes (50 sectors) + + +%define BASE 0x100 ; 0x0100:0x0 = 0x1000 +%define KSIZE 50 + +[BITS 16] +[ORG 0x0] + +; Code starts here, jump to our real entry point, skipping print +jmp start + +; print string using BIOS +print: + push ax + push bx + .start: + lodsb ; ds:si -> al + cmp al,0 + jz .fin + mov ah,0x0E ; 0x0e function of BIOS 0x10 interruption + mov bx,0x07 ; bx -> attribute, al -> ascii + int 0x10 + jmp .start + + .fin: + pop bx + pop ax + ret + +; Entry point +start: + mov [bootdrv],dl ; boot drive + +; Stack and section initialization at 0x07C0 + mov ax,0x07C0 + mov ds,ax + mov es,ax + mov ax,0x8000 ; stack at 0xFFFF + mov ss,ax + mov sp, 0xf000 + +; print 'Loading kernel ...' + mov si, ldKernel + call print + +; Load kernel + xor ax,ax + int 0x13 + + push es + mov ax,BASE + mov es,ax + mov bx,0 + mov ah,2 + mov al,KSIZE + mov ch,0 + mov cl,2 + mov dh,0 + mov dl,[bootdrv] + int 0x13 + pop es + +; GDT pointer + mov ax,gdtend ; GDT limit + mov bx,gdt + sub ax,bx + mov word [gdtptr],ax + + xor eax,eax ; GDT linear address + xor ebx,ebx + mov ax,ds + mov ecx,eax + shl ecx,4 + mov bx,gdt + add ecx,ebx + mov dword [gdtptr+2],ecx + +; pmode + cli + lgdt [gdtptr] ; load GDT + mov eax, cr0 + or ax,1 + mov cr0,eax ; enter Protected Mode + + jmp next +next: + mov ax,0x10 ; data segment + mov ds,ax + mov fs,ax + mov gs,ax + mov es,ax + mov ss,ax + mov esp,0x9F000 + + jmp dword 0x8:0x1000 ; jump to kernel _start at 0x1000 of 'second' selector (*8) + + +;-------------------------------------------------------------------- +bootdrv: db 0 +ldKernel db "Loading kernel ...",13,10,0 +;-------------------------------------------------------------------- +gdt: + db 0,0,0,0,0,0,0,0 +gdt_cs: + db 0xFF,0xFF,0x0,0x0,0x0,10011011b,11011111b,0x0 +gdt_ds: + db 0xFF,0xFF,0x0,0x0,0x0,10010011b,11011111b,0x0 +gdtend: + +;-------------------------------------------------------------------- +gdtptr: + dw 0 ; limit + dd 0 ; base + + +;-------------------------------------------------------------------- +;; fill remaining space with NOPs +times 510-($-$$) db 144 +dw 0xAA55 \ No newline at end of file diff --git a/kernel/boot/gdt.c b/kernel/boot/gdt.c new file mode 100644 index 0000000..f617142 --- /dev/null +++ b/kernel/boot/gdt.c @@ -0,0 +1,101 @@ +/* + *'freely' inspired by http://jojo.ouvaton.org/dossiers/boot_sector/tutorial02.html + * (actually, that's mostly copied, with minor compilation fixes) + */ +#include "kernel.h" +#include "klibc.h" + +#define GDTBASE 0x800 /* Physical address of GDT */ +#define GDTSIZE 0xFF /* Maximum table size (in entries) */ + +/* Segment descriptor */ +struct gdtdesc { + u16 lim0_15; + u16 base0_15; + u8 base16_23; + u8 acces; + u8 lim16_19 : 4; + u8 other : 4; + u8 base24_31; +} __attribute__ ((packed)); + +/* GDTR register */ +struct gdtr { + u16 limite ; + u32 base ; +} __attribute__ ((packed)); +struct gdtr kgdtr; + + +struct gdtdesc kgdt[GDTSIZE] = {{0, 0, 0, 0, 0, 0, 0}}; +unsigned int kgdtptr = 1; + +void init_code_desc(u32 base, u32 limite, struct gdtdesc* desc); +void init_data_desc(u32 base, u32 limite, struct gdtdesc* desc); +void add_gdt_desc(struct gdtdesc desc); +void init_gdt(void); + + + +void init_gdt_desc(u32 base, u32 limite, u8 acces, u8 other, struct gdtdesc* desc) { + desc->lim0_15 = (limite & 0xffff); + desc->base0_15 = (base & 0xffff); + desc->base16_23 = (base & 0xff0000)>>16; + desc->acces = acces; + desc->lim16_19 = (limite & 0xf0000)>>16; + desc->other = (other & 0xf); + desc->base24_31 = (base & 0xff000000)>>24; + return; +} + + +void init_code_desc(u32 base, u32 limite, struct gdtdesc* desc) { + init_gdt_desc(base, limite, 0x9B, 0x0D, desc); +} + +void init_data_desc(u32 base, u32 limite, struct gdtdesc* desc) { + init_gdt_desc(base, limite, 0x93, 0x0D, desc); +} + +void add_gdt_desc(struct gdtdesc desc) { + kgdt[kgdtptr] = desc; + kgdtptr++; +} + +void init_gdt(void) { + struct gdtdesc code, data, stack; + + /* initialisation des descripteurs de segment */ + init_code_desc(0x0, 0xFFFFF, &code); + init_data_desc(0x0, 0xFFFFF, &data); + init_gdt_desc(0, 0x10, 0x97, 0x0D, &stack); + add_gdt_desc(code); + add_gdt_desc(data); + add_gdt_desc(stack); + + /* initialisation de la structure pour GDTR */ + kgdtr.limite = GDTSIZE*8; + kgdtr.base = GDTBASE; + + /* recopie de la GDT a son adresse */ + memcpy((void*)kgdtr.base, kgdt, kgdtr.limite); + + /* chargement du registre GDTR */ + asm("lgdtl (kgdtr)"); + + /* initialisation des segments */ + asm(" movw $0x10,%ax \n \ + movw %ax, %ds \n \ + movw %ax, %es \n \ + movw %ax, %fs \n \ + movw %ax, %gs \n \ + movw $0x18,%ax \n \ + movw %ax, %ss \n \ + movl $0x1FFFF,%esp \n \ + nop \n \ + nop \n \ + ljmp $0x08,$next \n \ + next: \n"); +} + + diff --git a/kernel/boot/idt.c b/kernel/boot/idt.c new file mode 100644 index 0000000..58667ad --- /dev/null +++ b/kernel/boot/idt.c @@ -0,0 +1,132 @@ +/* + *'freely' inspired by http://jojo.ouvaton.org/dossiers/boot_sector/tutorial02.html + * (actually, that's mostly copied, with minor compilation fixes) + */ +#include "kernel.h" +#include "klibc.h" + +#define IDTBASE 0 /* GDT Physical address */ +#define IDTSIZE 256 /* Max descriptor count */ +#define INTGATE 0x8E00 /* Interruptions */ +#define TRAPGATE 0x8F00 /* Syscalls */ +#define TASKGATE 0x8500 /* Task switching */ + +/* segment descriptor */ +struct idtdesc { + u16 offset0_15; + u16 select; + u16 type; + u16 offset16_31; +} __attribute__ ((packed)); + +/* IDTR register */ +struct idtr { + u16 limite; + u32 base; +} __attribute__ ((packed)); + +struct idtr kidtr; + +/* IDT table */ +struct idtdesc kidt[IDTSIZE] = {{0, 0, 0, 0}}; + +/* pointer on a free IDT entry */ +unsigned int kidtptr = 0; + +void default_int(void); +void k_int0(void); +void k_int1(void); +void k_int2(void); +void k_int3(void); +void k_int4(void); +void k_int5(void); +void k_int6(void); +void k_int7(void); +void k_int8(void); +void k_int9(void); +void k_int10(void); +void k_int11(void); +void k_int12(void); +void k_int13(void); +void k_int14(void); +void k_int15(void); +void k_int16(void); +void k_int17(void); +void k_int18(void); +void k_irq0(void); +void k_irq1(void); +void k_irq2(void); +void k_irq3(void); +void k_irq4(void); +void k_irq5(void); +void k_irq6(void); +void k_irq7(void); +void k_irq8(void); + + +void init_idt_desc(u32 offset, u16 select, u16 type, struct idtdesc* desc) { + desc->offset0_15 = (offset & 0xffff); + desc->select = select; + desc->type = type; + desc->offset16_31 = (offset & 0xffff0000) >> 16; + return; +} + + +void add_idt_desc(struct idtdesc desc) { + kidt[kidtptr++] = desc; + return; +} + + +void init_idt(void) { + struct idtdesc desc; + int i; + + + for(i=0;i> 4; + int b = c & 0xF; + + char *drive_type[6] = { + "none", + "360kb 5.25in", + "1.2mb 5.25in", + "720kb 3.5in", + "1.44mb 3.5in", + "2.88mb 3.5in" + }; + + + memcpy(floppy_info->drive[0].type, drive_type[a], + strlen(drive_type[a]) + 1); + memcpy(floppy_info->drive[1].type, drive_type[b], + strlen(drive_type[b]) + 1); + + floppy_info->count = 0; + if (a != 0) + floppy_info->count++; + if (b != 0) + floppy_info->count++; + + return 0; +} + +void floppy_print_info(struct floppy_info *floppy_info) +{ + printf("%d floppy drive(s)\n", floppy_info->count); + if (floppy_info->count) + { + printf("Floppy %d type %s\n", 0, floppy_info->drive[0].type); + if (floppy_info->count == 2) + { + printf("Floppy %d type %s\n", 1, floppy_info->drive[1].type); + } + } + +} + +int floppy_get_status(void) +{ + unsigned char c = inb(0x1F7); + return c; +} diff --git a/kernel/drivers/floppy.h b/kernel/drivers/floppy.h new file mode 100644 index 0000000..f2c5302 --- /dev/null +++ b/kernel/drivers/floppy.h @@ -0,0 +1,14 @@ +struct floppy_drive { + char type[16]; + u8 status; +}; + +struct floppy_info { + int count; + struct floppy_drive drive[2]; +}; + +int floppy_get_info(struct floppy_info *floppy_info); +void floppy_print_info(struct floppy_info *floppy_info); + +int floppy_get_status(void); \ No newline at end of file diff --git a/kernel/drivers/keyboard.c b/kernel/drivers/keyboard.c new file mode 100644 index 0000000..ca772ac --- /dev/null +++ b/kernel/drivers/keyboard.c @@ -0,0 +1,101 @@ +#include "kernel.h" + +unsigned char kbdmap[] = { + 0x1B, 0x1B, 0x1B, 0x1B, /* esc (0x01) */ + '1', '!', '1', '1', + '2', '@', '2', '2', + '3', '#', '3', '3', + '4', '$', '4', '4', + '5', '%', '5', '5', + '6', '^', '6', '6', + '7', '&', '7', '7', + '8', '*', '8', '8', + '9', '(', '9', '9', + '0', ')', '0', '0', + '-', '_', '-', '-', + '=', '+', '=', '=', + 0x08, 0x08, 0x7F, 0x08, /* backspace */ + 0x09, 0x09, 0x09, 0x09, /* tab */ + 'q', 'Q', 'q', 'q', + 'w', 'W', 'w', 'w', + 'e', 'E', 'e', 'e', + 'r', 'R', 'r', 'r', + 't', 'T', 't', 't', + 'y', 'Y', 'y', 'y', + 'u', 'U', 'u', 'u', + 'i', 'I', 'i', 'i', + 'o', 'O', 'o', 'o', + 'p', 'P', 'p', 'p', + '[', '{', '[', '[', + ']', '}', ']', ']', + 0x0A, 0x0A, 0x0A, 0x0A, /* enter */ + 0xFF, 0xFF, 0xFF, 0xFF, /* ctrl */ + 'a', 'A', 'a', 'a', + 's', 'S', 's', 's', + 'd', 'D', 'd', 'd', + 'f', 'F', 'f', 'f', + 'g', 'G', 'g', 'g', + 'h', 'H', 'h', 'h', + 'j', 'J', 'j', 'j', + 'k', 'K', 'k', 'k', + 'l', 'L', 'l', 'l', + ';', ':', ';', ';', + 0x27, 0x22, 0x27, 0x27, /* '" */ + '`', '~', '`', '`', /* `~ */ + 0xFF, 0xFF, 0xFF, 0xFF, /* Lshift (0x2a) */ + '\\', '|', '\\', '\\', + 'z', 'Z', 'z', 'z', + 'x', 'X', 'x', 'x', + 'c', 'C', 'c', 'c', + 'v', 'V', 'v', 'v', + 'b', 'B', 'b', 'b', + 'n', 'N', 'n', 'n', + 'm', 'M', 'm', 'm', + 0x2C, 0x3C, 0x2C, 0x2C, /* ,< */ + 0x2E, 0x3E, 0x2E, 0x2E, /* .> */ + 0x2F, 0x3F, 0x2F, 0x2F, /* /? */ + 0xFF, 0xFF, 0xFF, 0xFF, /* Rshift (0x36) */ + 0xFF, 0xFF, 0xFF, 0xFF, /* (0x37) */ + 0xFF, 0xFF, 0xFF, 0xFF, /* (0x38) */ + 0xFF, 0xFF, 0xFF, 0xFF, /* (0x39) */ + 0xFF, 0xFF, 0xFF, 0xFF, /* (0x3a) */ + 0xFF, 0xFF, 0xFF, 0xFF, /* (0x3b) */ + 0xFF, 0xFF, 0xFF, 0xFF, /* (0x3c) */ + 0xFF, 0xFF, 0xFF, 0xFF, /* (0x3d) */ + 0xFF, 0xFF, 0xFF, 0xFF, /* (0x3e) */ + 0xFF, 0xFF, 0xFF, 0xFF, /* (0x3f) */ + 0xFF, 0xFF, 0xFF, 0xFF, /* (0x40) */ + 0xFF, 0xFF, 0xFF, 0xFF, /* (0x41) */ + 0xFF, 0xFF, 0xFF, 0xFF, /* (0x42) */ + 0xFF, 0xFF, 0xFF, 0xFF, /* (0x43) */ + 0xFF, 0xFF, 0xFF, 0xFF, /* (0x44) */ + 0xFF, 0xFF, 0xFF, 0xFF, /* (0x45) */ + 0xFF, 0xFF, 0xFF, 0xFF, /* (0x46) */ + 0xFF, 0xFF, 0xFF, 0xFF, /* (0x47) */ + 0xFF, 0xFF, 0xFF, 0xFF, /* (0x48) */ + 0xFF, 0xFF, 0xFF, 0xFF, /* (0x49) */ + 0xFF, 0xFF, 0xFF, 0xFF, /* (0x4a) */ + 0xFF, 0xFF, 0xFF, 0xFF, /* (0x4b) */ + 0xFF, 0xFF, 0xFF, 0xFF, /* (0x4c) */ + 0xFF, 0xFF, 0xFF, 0xFF, /* (0x4d) */ + 0xFF, 0xFF, 0xFF, 0xFF, /* (0x4e) */ + 0xFF, 0xFF, 0xFF, 0xFF, /* (0x4f) */ + 0xFF, 0xFF, 0xFF, 0xFF, /* (0x50) */ + 0xFF, 0xFF, 0xFF, 0xFF, /* (0x51) */ + 0xFF, 0xFF, 0xFF, 0xFF, /* (0x52) */ + 0xFF, 0xFF, 0xFF, 0xFF, /* (0x53) */ + 0xFF, 0xFF, 0xFF, 0xFF, /* (0x54) */ + 0xFF, 0xFF, 0xFF, 0xFF, /* (0x55) */ + 0xFF, 0xFF, 0xFF, 0xFF, /* (0x56) */ + 0xFF, 0xFF, 0xFF, 0xFF, /* (0x57) */ + 0xFF, 0xFF, 0xFF, 0xFF, /* (0x58) */ + 0xFF, 0xFF, 0xFF, 0xFF, /* (0x59) */ + 0xFF, 0xFF, 0xFF, 0xFF, /* (0x5a) */ + 0xFF, 0xFF, 0xFF, 0xFF, /* (0x5b) */ + 0xFF, 0xFF, 0xFF, 0xFF, /* (0x5c) */ + 0xFF, 0xFF, 0xFF, 0xFF, /* (0x5d) */ + 0xFF, 0xFF, 0xFF, 0xFF, /* (0x5e) */ + 0xFF, 0xFF, 0xFF, 0xFF, /* (0x5f) */ + 0xFF, 0xFF, 0xFF, 0xFF, /* (0x60) */ + 0xFF, 0xFF, 0xFF, 0xFF /* (0x61) */ +}; diff --git a/kernel/drivers/memory.c b/kernel/drivers/memory.c new file mode 100644 index 0000000..1b380c2 --- /dev/null +++ b/kernel/drivers/memory.c @@ -0,0 +1,4 @@ +#include "kernel.h" +#include "klibc.h" +#include "memory.h" + diff --git a/kernel/drivers/memory.h b/kernel/drivers/memory.h new file mode 100644 index 0000000..e69de29 diff --git a/kernel/drivers/processor.c b/kernel/drivers/processor.c new file mode 100644 index 0000000..d4004c6 --- /dev/null +++ b/kernel/drivers/processor.c @@ -0,0 +1,50 @@ +/* + * processor.c + * + * + * Created by Jean-Yves Lamoureux on 12/19/09. + * Copyright 2009 Frob. All rights reserved. + * + */ +#include "kernel.h" +#include "klibc.h" +#include "processor.h" + + +int processor_get_info(struct processor_info *processor_info) +{ + /* Vendor String */ + int code = CPUID_GETVENDORSTRING; + unsigned int where[5]; + char *s; + asm volatile ("cpuid":"=a" (*where), "=b"(*(where + 1)), + "=c"(*(where + 2)), "=d"(*(where + 3)):"0"(code)); + + s = (char *)where; + + unsigned int a = 0; + unsigned int b = where[1]; + unsigned int d = where[3]; + unsigned int c = where[2]; + + where[0] = b; + where[1] = d; + where[2] = c; + where[3] = 0; + + memcpy(processor_info->vendor, where, 13); + + /* Features */ + code = CPUID_GETFEATURES; + asm volatile ("cpuid":"=a" (a), "=d"(d):"0"(code):"ecx", "ebx"); + processor_info->features = a; + + return 0; +} + +void processor_print_info(struct processor_info *processor_info) +{ + printf("CPU%d\n", processor_info->id); + printf("Vendor ID : %s\n", processor_info->vendor); + printf("Features : 0x%x\n", processor_info->features); +} diff --git a/kernel/drivers/processor.h b/kernel/drivers/processor.h new file mode 100644 index 0000000..b30a6be --- /dev/null +++ b/kernel/drivers/processor.h @@ -0,0 +1,81 @@ + +enum cpuid_requests { + CPUID_GETVENDORSTRING, + CPUID_GETFEATURES, + CPUID_GETTLB, + CPUID_GETSERIAL, + + CPUID_INTELEXTENDED=0x80000000, + CPUID_INTELFEATURES, + CPUID_INTELBRANDSTRING, + CPUID_INTELBRANDSTRINGMORE, + CPUID_INTELBRANDSTRINGEND, +}; + +enum { + CPUID_FEAT_ECX_SSE3 = 1 << 0, + CPUID_FEAT_ECX_PCLMUL = 1 << 1, + CPUID_FEAT_ECX_DTES64 = 1 << 2, + CPUID_FEAT_ECX_MONITOR = 1 << 3, + CPUID_FEAT_ECX_DS_CPL = 1 << 4, + CPUID_FEAT_ECX_VMX = 1 << 5, + CPUID_FEAT_ECX_SMX = 1 << 6, + CPUID_FEAT_ECX_EST = 1 << 7, + CPUID_FEAT_ECX_TM2 = 1 << 8, + CPUID_FEAT_ECX_SSSE3 = 1 << 9, + CPUID_FEAT_ECX_CID = 1 << 10, + CPUID_FEAT_ECX_FMA = 1 << 12, + CPUID_FEAT_ECX_CX16 = 1 << 13, + CPUID_FEAT_ECX_ETPRD = 1 << 14, + CPUID_FEAT_ECX_PDCM = 1 << 15, + CPUID_FEAT_ECX_DCA = 1 << 18, + CPUID_FEAT_ECX_SSE4_1 = 1 << 19, + CPUID_FEAT_ECX_SSE4_2 = 1 << 20, + CPUID_FEAT_ECX_x2APIC = 1 << 21, + CPUID_FEAT_ECX_MOVBE = 1 << 22, + CPUID_FEAT_ECX_POPCNT = 1 << 23, + CPUID_FEAT_ECX_XSAVE = 1 << 26, + CPUID_FEAT_ECX_OSXSAVE = 1 << 27, + CPUID_FEAT_ECX_AVX = 1 << 28, + + CPUID_FEAT_EDX_FPU = 1 << 0, + CPUID_FEAT_EDX_VME = 1 << 1, + CPUID_FEAT_EDX_DE = 1 << 2, + CPUID_FEAT_EDX_PSE = 1 << 3, + CPUID_FEAT_EDX_TSC = 1 << 4, + CPUID_FEAT_EDX_MSR = 1 << 5, + CPUID_FEAT_EDX_PAE = 1 << 6, + CPUID_FEAT_EDX_MCE = 1 << 7, + CPUID_FEAT_EDX_CX8 = 1 << 8, + CPUID_FEAT_EDX_APIC = 1 << 9, + CPUID_FEAT_EDX_SEP = 1 << 11, + CPUID_FEAT_EDX_MTRR = 1 << 12, + CPUID_FEAT_EDX_PGE = 1 << 13, + CPUID_FEAT_EDX_MCA = 1 << 14, + CPUID_FEAT_EDX_CMOV = 1 << 15, + CPUID_FEAT_EDX_PAT = 1 << 16, + CPUID_FEAT_EDX_PSE36 = 1 << 17, + CPUID_FEAT_EDX_PSN = 1 << 18, + CPUID_FEAT_EDX_CLF = 1 << 19, + CPUID_FEAT_EDX_DTES = 1 << 21, + CPUID_FEAT_EDX_ACPI = 1 << 22, + CPUID_FEAT_EDX_MMX = 1 << 23, + CPUID_FEAT_EDX_FXSR = 1 << 24, + CPUID_FEAT_EDX_SSE = 1 << 25, + CPUID_FEAT_EDX_SSE2 = 1 << 26, + CPUID_FEAT_EDX_SS = 1 << 27, + CPUID_FEAT_EDX_HTT = 1 << 28, + CPUID_FEAT_EDX_TM1 = 1 << 29, + CPUID_FEAT_EDX_IA64 = 1 << 30, + CPUID_FEAT_EDX_PBE = 1 << 31 +}; + +struct processor_info { + int id; + char vendor[13]; + unsigned int features; +}; + + +int processor_get_info(struct processor_info *processor_info); +void processor_print_info(struct processor_info *processor_info); \ No newline at end of file diff --git a/kernel/drivers/timer.c b/kernel/drivers/timer.c new file mode 100644 index 0000000..32f6ea2 --- /dev/null +++ b/kernel/drivers/timer.c @@ -0,0 +1,42 @@ + +#include "kernel.h" +#include "klibc.h" +#include "timer.h" + +u32 ticks = 0; + +void timer_phase(int hz) +{ + unsigned int divisor = 1193180 / hz; /* Calculate our divisor */ + /* + 0x43 is the Mode/Command register + + From http://wiki.osdev.org/Programmable_Interval_Timer#Read_Back_Status_Byte : + Bits Usage + 6 and 7 Select channel : + 0 0 = Channel 0 + 0 1 = Channel 1 + 1 0 = Channel 2 + 1 1 = Read-back command (8254 only) + 4 and 5 Access mode : + 0 0 = Latch count value command + 0 1 = Access mode: lobyte only + 1 0 = Access mode: hibyte only + 1 1 = Access mode: lobyte/hibyte + 1 to 3 Operating mode : + 0 0 0 = Mode 0 (interrupt on terminal count) + 0 0 1 = Mode 1 (hardware re-triggerable one-shot) + 0 1 0 = Mode 2 (rate generator) + 0 1 1 = Mode 3 (square wave generator) + 1 0 0 = Mode 4 (software triggered strobe) + 1 0 1 = Mode 5 (hardware triggered strobe) + 1 1 0 = Mode 2 (rate generator, same as 010b) + 1 1 1 = Mode 3 (square wave generator, same as 011b) + 0 BCD/Binary mode: 0 = 16-bit binary, 1 = four-digit BCD + + */ + unsigned short command = 0b00110110; + outb(0x43, command); + outb(0x40, divisor & 0xFF); /* Set low byte of divisor */ + outb(0x40, divisor >> 8); /* Set high byte of divisor */ +} \ No newline at end of file diff --git a/kernel/drivers/timer.h b/kernel/drivers/timer.h new file mode 100644 index 0000000..7c201a5 --- /dev/null +++ b/kernel/drivers/timer.h @@ -0,0 +1,2 @@ +extern u32 ticks; +void timer_phase(int hz); \ No newline at end of file diff --git a/kernel/kernel.c b/kernel/kernel.c index 0d07058..83c5d32 100644 --- a/kernel/kernel.c +++ b/kernel/kernel.c @@ -1,8 +1,8 @@ -/* - * libcaca Canvas for ultrafast compositing of Unicode letters +/* + * libcaca * libcaca Colour ASCII-Art library - * Copyright (c) 2006 Sam Hocevar - * 2006 Jean-Yves Lamoureux + * Copyright (c) 2006 Sam Hocevar + * 2006-2009 Jean-Yves Lamoureux * All Rights Reserved * * $Id$ @@ -14,388 +14,61 @@ * http://sam.zoy.org/wtfpl/COPYING for more details. */ -/* +/* * This file contains replacement functions for the standard C library * that must be used when building libcaca and libcaca into a kernel. */ #include "config.h" - #include "caca_types.h" #ifdef __KERNEL__ -#define IS_DIGIT(x) (x>='0' && x<='9') -#define IS_ALPHA(x) (x>='A' && x<='z') -#define IS_UPPER(x) (x>='A' && x<='Z') -#define IS_LOWER(x) (x>='a' && x<='z') -#define UPPER(x) (IS_LOWER(x)?(x+('A'-'a')):x) -#define LOWER(x) (IS_UPPER(x)?(x-('a'-'A')):x) - -/* Our default seed for random number generator */ -static int seed = 0x68743284; - -/* Our memory mapping */ -static uint32_t *freemem = (uint32_t*) 0x00200000; - -/* Multiboot kernel entry point */ -void cmain(unsigned long int magic, unsigned long int addr) -{ - static char const text[] = "Booting libcaca kernel..."; - char const *ptr = text; - char *video = (char*)0xB8000; - - char *argv[] = { NULL }; - int argc = 0; - - /* Print a text message to say hello */ - while(*ptr) - *video = *ptr++; video += 2; - - /* Launch the main program */ - main(argc, argv); -} - -/* stdlib.h functions */ -void *malloc(size_t size) -{ - uint32_t *p = freemem; - if(!size) - return NULL; - size = (size + 0x7) / 4; - *p = size; - freemem += size + 1; - return p + 1; -} - -void free(void *ptr) -{ - return; -} - -void *realloc(void *ptr, size_t size) -{ - uint32_t oldsize; - void *p; - - if(!size) - return NULL; - - if(!ptr) - oldsize = 0; - else +#include "klibc.h" +#include "boot/stage2.h" +#include "kernel.h" +#include "drivers/processor.h" +#include "drivers/floppy.h" +#include "drivers/timer.h" + +extern char const * const * caca_get_display_driver_list(void); + +/* C entry point, called from stage2 */ +int kmain(void) +{ + struct processor_info processor_info; + struct floppy_info floppy_info; + + printf("_start at 0x%x\n", _start); + printf("kmain() at 0x%x\n", kmain); + + processor_get_info(&processor_info); + processor_print_info(&processor_info); + + floppy_get_info(&floppy_info); + floppy_print_info(&floppy_info); + + enable_interrupt(1); // Enable Keyboard Interrupt (IRQ1) + enable_interrupt(0); // Enable IRQ0 (timer) + enable_interrupt(13); + timer_phase(100); // Fire IRQ0 each 1/100s + + + printf("Waiting 1s\n"); + sleep(1); + printf("Waiting 2s\n"); + sleep(2); + printf("Waiting 3s\n"); + sleep(3); + printf("Ok\n"); + //caca_get_display_driver_list(); + + + while (1) { - oldsize = ((uint32_t *)ptr)[-1]; - if(oldsize >= size) - return ptr; + } - - p = malloc(size); - memcpy(p, ptr, oldsize); - return p; } -char *getenv(const char *name) -{ - return NULL; -} - -int getpid(void) -{ - return 0x1337; -} - -void srand(unsigned int s) -{ - seed = rand(); -} - -int time(void *dummy) -{ - return rand(); -} - -int rand(void) -{ - seed = (seed * 0x7f32ba17) ^ 0xf893a735; - return seed % RAND_MAX; -} - -int abs(int j) -{ - if(j < 0) - return -j; - return j; -} - -void exit(int status) -{ - /* FIXME: reboot? */ - while(1); -} - -int atexit(void (*function)(void)) -{ - /* FIXME: register function */ - return 0; -} - -/* string.h functions */ -void *memset(void *s, int c, size_t n) -{ - uint8_t *ptr = s; - - while(n--) - *ptr++ = c; - - return s; -} - -void *memcpy(void *dest, const void *src, size_t n) -{ - uint8_t *destptr = dest; - uint8_t const *srcptr = src; - - while(n--) - *destptr++ = *srcptr++; - - return dest; -} - -void *memmove(void *dest, const void *src, size_t n) -{ - memcpy(freemem, src, n); - memcpy(dest, freemem, n); - return dest; -} - -size_t strlen(const char *s) -{ - int len = 0; - - while(*s++) - len++; - - return len; -} - -int strcmp(const char *s1, const char *s2) -{ - while(*s1 && *s1 == *s2) - { - s1++; - s2++; - } - - return (int)*s1 - (int)*s2; -} - -int strcasecmp(const char *s1, const char *s2) -{ - while(*s1 && *s2 && UPPER(*s1) == UPPER(*s2)) - { - s1++; - s2++; - } - - return (int)UPPER(*s1) - (int)UPPER(*s2); -} - -int memcmp(const void *_s1, const void *_s2, size_t n) -{ - uint8_t const *s1 = _s1, *s2 = _s2; - - while(n--) - { - if(*s1 != *s2) - return (int)*s1 - (int)*s2; - s1++; - s2++; - } - return 0; -} - -char *strdup(const char *s) -{ - char *new; - unsigned int len = strlen(s); - - new = malloc(len + 1); - memcpy(new, s, len + 1); - - return new; -} - -char *strchr(const char *s, int c) -{ - do - if(*s == c) - return (char *)(intptr_t)s; - while(*s++); - - return NULL; -} - -/* stdarg.h functions */ -int vsnprintf(char *str, size_t size, const char *format, va_list ap) -{ - /* FIXME */ - return 0; -} - -/* stdio.h functions */ -FILE *fopen(const char *path, const char *mode) -{ - /* FIXME */ - return NULL; -} - -int feof(FILE *stream) -{ - /* FIXME */ - return 0; -} - -char *fgets(char *s, int size, FILE *stream) -{ - /* FIXME */ - return NULL; -} - -size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream) -{ - return 0; -} - -int fclose(FILE *fp) -{ - /* FIXME */ - return 0; -} - -int printf(const char *format, ...) -{ - /* FIXME */ - return 0; -} - -int fprintf(FILE *stream, const char *format, ...) -{ - /* FIXME */ - return 0; -} - -int fflush(FILE *stream) -{ - /* FIXME */ - return 0; -} - -int sprintf(char *str, const char *format, ...) -{ - /* FIXME */ - return 0; -} - -int sscanf(const char *str, const char *format, ...) -{ - /* FIXME */ - return 0; -} - -/* unistd.h functions */ -void usleep(unsigned long usec) -{ - /* FIXME */ - return; -} - -/* time.h functions */ -int gettimeofday(struct timeval *tv, struct timezone *tz) -{ - static int usec = 0; - static int sec = 0; - - /* FIXME */ - usec += 10000; - if(usec > 1000000) - { - sec++; - usec -= 1000000; - } - - tv->tv_sec = sec; - tv->tv_usec = usec; - - return 0; -} - -/* math.h functions */ -double cos(double x) -{ - double ret = 0.0; -#ifdef HAVE_FSIN_FCOS - asm volatile("fcos" : "=t" (ret) : "0" (x)); -#else - double x2; - double num = 1.0; - double fact = 1.0; - int i; - - x = x - ((double)(int)(x / (2 * M_PI))) * (2 * M_PI); - x2 = x * x; - - /* cos(x) = 1/0! - x^2/2! + x^4/4! - x^6/6! ... */ - for(i = 0; i < 10; i++) - { - ret += num / fact; - num *= - x2; - fact *= (2 * i + 1) * (2 * i + 2); - } -#endif - return ret; -} - -double sin(double x) -{ - double ret = 0.0; -#ifdef HAVE_FSIN_FCOS - asm volatile("fsin" : "=t" (ret) : "0" (x)); -#else - double x2; - double num; - double fact = 1.0; - int i; - - x = x - ((double)(int)(x / (2 * M_PI))) * (2 * M_PI); - x2 = x * x; - num = x; - - /* sin(x) = x/1! - x^3/3! + x^5/5! - x^7/7! ... */ - for(i = 0; i < 10; i++) - { - ret += num / fact; - num *= - x2; - fact *= (2 * i + 2) * (2 * i + 3); - } -#endif - return ret; -} - -double sqrt(double x) -{ - double ret = x; - int i; - - /* This is Newton's method */ - for(i = 0; i < 10; i++) - ret = (ret * ret + x) / (ret * 2.0); - - return ret; -} - -/* errno.h stuff */ - -int errno = 0; #endif /* __KERNEL__ */ diff --git a/kernel/kernel.h b/kernel/kernel.h index 456e2fd..efe0fe9 100644 --- a/kernel/kernel.h +++ b/kernel/kernel.h @@ -1,7 +1,7 @@ /* * libcaca Canvas for ultrafast compositing of Unicode letters * libcaca Colour ASCII-Art library - * Copyright (c) 2006 Sam Hocevar + * Copyright (c) 2006 Sam Hocevar * All Rights Reserved * * $Id$ @@ -18,122 +18,24 @@ * that must be used when building libcaca and libcaca into a kernel. */ -/* Various defines */ -#define NULL ((void *)0) -#define EOF (-1) -#define BUFSIZ 4096 -#define RAND_MAX ((unsigned int)0x8000000) -#define INT_MAX ((int)0x7fffffff) -#define M_PI 3.14159265358979323846 -#define __BYTE_ORDER 1 -#define __BIG_ENDIAN 2 -/* Assembly code for outb and inb */ -extern inline void outb(unsigned char val, unsigned short port); -extern inline unsigned char inb(unsigned short port); -extern inline void outb(unsigned char val, unsigned short port) -{ - __asm__ __volatile__ ("outb %b0,%w1" : : "a" (val), "Nd" (port)); -} -extern inline unsigned char inb(unsigned short port) -{ - unsigned char tmp; - __asm__ __volatile__ ("inb %w1,%0" : "=a" (tmp) : "Nd" (port)); - return tmp; -} +extern void init_gdt(void); +void init_pic(void); +void init_idt(void); +void putcar(unsigned char c); +void dump_gdt(void); -/* Various typedefs -- some are x86-specific */ -#define CUSTOM_INTTYPES -typedef unsigned int size_t; +void disable_interrupt(char i); +void enable_interrupt(char i); -typedef struct file -{ - void *mem; -} FILE; -struct timeval { - int tv_sec; - int tv_usec; -}; +#define cli __asm__("cli"::) +#define sti __asm__("sti"::) -struct timezone { - int tz_minuteswest; - int tz_dsttime; -}; -/* Multiboot kernel entry point */ -void cmain(unsigned long int magic, unsigned long int addr); /* The application's entry point */ int main(int argc, char *argv[]); -/* stdlib.h functions */ -void *malloc(size_t size); -void free(void *ptr); -void *realloc(void *ptr, size_t size); -char *getenv(const char *name); -int rand(void); -int abs(int j); -void exit(int status); -void srand(unsigned int s); -int atexit(void (*function)(void)); -FILE *stdin, *stdout, *stderr; - -/* string.h functions */ -void *memset(void *s, int c, size_t n); -void *memcpy(void *dest, const void *src, size_t n); -void *memmove(void *dest, const void *src, size_t n); -size_t strlen(const char *s); -int strcmp(const char *s1, const char *s2); -int strcasecmp(const char *s1, const char *s2); -int memcmp(const void *s1, const void *s2, size_t n); -char *strdup(const char *s); -char *strchr(const char *s, int c); - -/* stdarg.h functions */ -typedef void * va_list; -#define va_start(v,a) v = (void *)((uintptr_t)(&a) + sizeof(a)) -#define va_end(v) -int vsnprintf(char *str, size_t size, const char *format, va_list ap); - -/* stdio.h functions */ -FILE *fopen(const char *path, const char *mode); -int feof(FILE *stream); -char *fgets(char *s, int size, FILE *stream); -size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream); -int fclose(FILE *fp); -int printf(const char *format, ...); -int fprintf(FILE *stream, const char *format, ...); -int fflush(FILE *stream); -int sprintf(char *str, const char *format, ...); -int sscanf(const char *str, const char *format, ...); - -/* unistd.h functions */ -void usleep(unsigned long usec); -int getpid(void); - -/* time.h functions */ -int gettimeofday(struct timeval *tv, struct timezone *tz); -int time(void *); - -/* math.h functions */ -double cos(double x); -double sin(double x); -double sqrt(double x); - -/* errno.h functions */ -#define ENOENT 2 /* No such file or directory */ -#define ENOMEM 12 /* Out of memory */ -#define EBUSY 16 /* Device or resource busy */ -#define ENODEV 19 /* No such device */ -#define EINVAL 22 /* Invalid argument */ -#define ENOTTY 25 /* Not a typewriter */ -#define ENOSYS 38 /* Function not implemented */ -extern int errno; - -/* arpa/inet.h functions */ -unsigned int htonl(unsigned int hostlong); -unsigned short htons(unsigned short hostlong); - diff --git a/kernel/klibc.c b/kernel/klibc.c new file mode 100644 index 0000000..0cf164b --- /dev/null +++ b/kernel/klibc.c @@ -0,0 +1,598 @@ +#include "config.h" +#include "caca_types.h" + +#include "klibc.h" +#include "drivers/timer.h" +#include "kernel.h" + + +void htoa(unsigned int value, char s[]); + +#define IS_DIGIT(x) (x>='0' && x<='9') +#define IS_ALPHA(x) (x>='A' && x<='z') +#define IS_UPPER(x) (x>='A' && x<='Z') +#define IS_LOWER(x) (x>='a' && x<='z') +#define UPPER(x) (IS_LOWER(x)?(x+('A'-'a')):x) +#define LOWER(x) (IS_UPPER(x)?(x-('a'-'A')):x) + +/* Our default seed for random number generator */ +static int seed = 0x68743284; + +/* Our memory mapping */ +static uint32_t *freemem = (uint32_t*) 0x00200000; +int kX = 0; +int kY = 0; + +void scroll(void) +{ + unsigned char* video, *tmp; + + for(video=(unsigned char*)0xB8000 ; video<(unsigned char*)0xB8FA0 ; video++){ + tmp = (unsigned char*) (video+1*160); + + if(tmp<(unsigned char*)0xB8FA0) + *video = *tmp; + else + *video = 0; + } + + kY-=1; + if(kY<0) + kY=0;} + +void putcar(unsigned char c) +{ + unsigned char* video; + + if(c==10){ + kX=0; + kY++; + } + else{ + video = (unsigned char*) (0xB8000+2*kX+160*kY); + *video = c; + *(video+1) = 0x07; + + kX++; + if(kX>79){ + kX = 0; + kY++; + } + if(kY >= 24) { + scroll(); + } + } +} + +void print(char *str) +{ + char const *ptr = str; + while(*ptr) { + putcar(*ptr++); + } +} + +void clearscreen(void) +{ + int x, y; + kX = 0; + kY = 0; + for(y = 0; y < 25; y++) + for(x = 0; x < 80; x++) { + putcar(' '); + } + kX = 0; + kY = 0; +} + +/* stdlib.h functions */ +void *malloc(size_t size) +{ + uint32_t *p = freemem; + if(!size) + return NULL; + size = (size + 0x7) / 4; + *p = size; + freemem += size + 1; + return p + 1; +} + +void free(void *ptr) +{ + return; +} + +void *realloc(void *ptr, size_t size) +{ + uint32_t oldsize; + void *p; + + if(!size) + return NULL; + + if(!ptr) + oldsize = 0; + else + { + oldsize = ((uint32_t *)ptr)[-1]; + if(oldsize >= size) + return ptr; + } + + p = malloc(size); + memcpy(p, ptr, oldsize); + return p; +} + +char *getenv(const char *name) +{ + return NULL; +} + +int getpid(void) +{ + return 0x1337; +} + +void srand(unsigned int s) +{ + seed = rand(); +} + +int time(void *dummy) +{ + return rand(); +} + +int rand(void) +{ + seed = (seed * 0x7f32ba17) ^ 0xf893a735; + return seed % RAND_MAX; +} + +int abs(int j) +{ + if(j < 0) + return -j; + return j; +} + +void exit(int status) +{ + /* FIXME: reboot? */ + while(1); +} + +int atexit(void (*function)(void)) +{ + /* FIXME: register function */ + return 0; +} + +/* string.h functions */ +void *memset(void *s, int c, size_t n) +{ + uint8_t *ptr = s; + + while(n--) + *ptr++ = c; + + return s; +} + +void *memcpy(void *dest, const void *src, size_t n) +{ + uint8_t *destptr = dest; + uint8_t const *srcptr = src; + + while(n--) + *destptr++ = *srcptr++; + + return dest; +} + +void *memmove(void *dest, const void *src, size_t n) +{ + memcpy(freemem, src, n); + memcpy(dest, freemem, n); + return dest; +} + +size_t strlen(const char *s) +{ + int len = 0; + + while(*s++) + len++; + + return len; +} + +int strcmp(const char *s1, const char *s2) +{ + while(*s1 && *s1 == *s2) + { + s1++; + s2++; + } + + return (int)*s1 - (int)*s2; +} + +int strcasecmp(const char *s1, const char *s2) +{ + while(*s1 && *s2 && UPPER(*s1) == UPPER(*s2)) + { + s1++; + s2++; + } + + return (int)UPPER(*s1) - (int)UPPER(*s2); +} + +int memcmp(const void *_s1, const void *_s2, size_t n) +{ + uint8_t const *s1 = _s1, *s2 = _s2; + + while(n--) + { + if(*s1 != *s2) + return (int)*s1 - (int)*s2; + s1++; + s2++; + } + return 0; +} + +char *strdup(const char *s) +{ + char *new; + unsigned int len = strlen(s); + + new = malloc(len + 1); + memcpy(new, s, len + 1); + + return new; +} + +char *strchr(const char *s, int c) +{ + do + if(*s == c) + return (char *)(intptr_t)s; + while(*s++); + + return NULL; +} + +/* stdarg.h functions */ +int vsnprintf(char *str, size_t size, const char *format, va_list ap) +{ + /* FIXME */ + return 0; +} + +/* stdio.h functions */ +FILE *fopen(const char *path, const char *mode) +{ + /* FIXME */ + return NULL; +} + +int feof(FILE *stream) +{ + /* FIXME */ + return 0; +} + +char *fgets(char *s, int size, FILE *stream) +{ + /* FIXME */ + return NULL; +} + +size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream) +{ + return 0; +} + +int fclose(FILE *fp) +{ + /* FIXME */ + return 0; +} + +int printf(const char *fmt, ...) +{ + char str[200]; + char tmp[100]; + args_list args; + args_start(args, fmt); + + char *s; + int ptr = 0; + int i = 0; + + for (; fmt[i]; ++i) { + if ((fmt[i]!='%') && (fmt[i]!='\\')) { + str[ptr++] = fmt[i]; + continue; + } else if (fmt[i] == '\\') { + switch (fmt[++i]) { + case 'a': str[ptr++] = '\a'; break; + case 'b': str[ptr++] = '\b'; break; + case 't': str[ptr++] = '\t'; break; + case 'n': str[ptr++] = '\n'; break; + case 'r': str[ptr++] = '\r'; break; + case '\\':str[ptr++] = '\\'; break; + } + continue; + } + + switch (fmt[++i]) { + case 's': + s = (char *)args_next(args, char *); + while (*s) + str[ptr++] = *s++; + break; + case 'c': + str[ptr++] = (char)args_next(args, int); + break; + case 'p': + case 'x': + htoa((unsigned long)args_next(args, unsigned long), tmp); + memcpy(&str[ptr], tmp, strlen(tmp)); + ptr+=strlen(tmp); + break; + case 'd': + itoa((unsigned long)args_next(args, unsigned long), tmp); + memcpy(&str[ptr], tmp, strlen(tmp)); + ptr+=strlen(tmp); + break; + case '%': + str[ptr++] = '%'; + break; + default: + str[ptr++] = fmt[i]; + break; + } + } + + str[ptr] = '\0'; + args_end(args); + + print(str); + + return 0; +} + +int fprintf(FILE *stream, const char *format, ...) +{ + /* FIXME */ + return 0; +} + +int fflush(FILE *stream) +{ + /* FIXME */ + return 0; +} + +int sprintf(char *str, const char *fmt, ...) +{ + char tmp[100]; + args_list args; + args_start(args, fmt); + + char *s; + int ptr = 0; + int i = 0; + + for (; fmt[i]; ++i) { + if ((fmt[i]!='%') && (fmt[i]!='\\')) { + str[ptr++] = fmt[i]; + continue; + } else if (fmt[i] == '\\') { + switch (fmt[++i]) { + case 'a': str[ptr++] = '\a'; break; + case 'b': str[ptr++] = '\b'; break; + case 't': str[ptr++] = '\t'; break; + case 'n': str[ptr++] = '\n'; break; + case 'r': str[ptr++] = '\r'; break; + case '\\':str[ptr++] = '\\'; break; + } + continue; + } + + switch (fmt[++i]) { + case 's': + s = (char *)args_next(args, char *); + while (*s) + str[ptr++] = *s++; + break; + case 'c': + str[ptr++] = (char)args_next(args, int); + break; + case 'p': + case 'x': + htoa((unsigned long)args_next(args, unsigned long), tmp); + memcpy(&str[ptr], tmp, strlen(tmp)); + ptr+=strlen(tmp); + break; + case 'd': + itoa((unsigned long)args_next(args, unsigned long), tmp); + memcpy(&str[ptr], tmp, strlen(tmp)); + ptr+=strlen(tmp); + break; + case '%': + str[ptr++] = '%'; + break; + default: + str[ptr++] = fmt[i]; + break; + } + } + + str[ptr] = '\0'; + args_end(args); + + return 0; +} + +int sscanf(const char *str, const char *format, ...) +{ + /* FIXME */ + return 0; +} + +/* unistd.h functions */ +void usleep(unsigned long usec) +{ + u32 start = ticks; + signed int diff = 0; + + while(1) { + diff = (signed int)(ticks - start); + if(diff >= (signed int)(usec/20)) break; + } +} + +void sleep(unsigned long sec) +{ + usleep(sec*1000); +} + +/* time.h functions */ + u64 rdtsc() { + u64 x; + __asm__ volatile ("rdtsc" : "=A" (x)); + return x; +} + +int gettimeofday(struct timeval *tv, struct timezone *tz) +{ + static int usec = 0; + static int sec = 0; + + /* FIXME */ + usec += 10000; + if(usec > 1000000) + { + sec++; + usec -= 1000000; + } + + tv->tv_sec = sec; + tv->tv_usec = usec; + + return 0; +} + +/* math.h functions */ +double cos(double x) +{ + double ret = 0.0; +#ifdef HAVE_FSIN_FCOS + asm volatile("fcos" : "=t" (ret) : "0" (x)); +#else + double x2; + double num = 1.0; + double fact = 1.0; + int i; + + x = x - ((double)(int)(x / (2 * M_PI))) * (2 * M_PI); + x2 = x * x; + + /* cos(x) = 1/0! - x^2/2! + x^4/4! - x^6/6! ... */ + for(i = 0; i < 10; i++) + { + ret += num / fact; + num *= - x2; + fact *= (2 * i + 1) * (2 * i + 2); + } +#endif + return ret; +} + +double sin(double x) +{ + double ret = 0.0; +#ifdef HAVE_FSIN_FCOS + asm volatile("fsin" : "=t" (ret) : "0" (x)); +#else + double x2; + double num; + double fact = 1.0; + int i; + + x = x - ((double)(int)(x / (2 * M_PI))) * (2 * M_PI); + x2 = x * x; + num = x; + + /* sin(x) = x/1! - x^3/3! + x^5/5! - x^7/7! ... */ + for(i = 0; i < 10; i++) + { + ret += num / fact; + num *= - x2; + fact *= (2 * i + 2) * (2 * i + 3); + } +#endif + return ret; +} + +double sqrt(double x) +{ + double ret = x; + int i; + + /* This is Newton's method */ + for(i = 0; i < 10; i++) + ret = (ret * ret + x) / (ret * 2.0); + + return ret; +} + + +/* reverse: reverse string s in place */ +void reverse(char s[]) +{ + int i, j; + char c; + + for (i = 0, j = strlen(s)-1; i 0); /* delete it */ + if (sign < 0) + s[i++] = '-'; + s[i] = '\0'; + reverse(s); +} + +void htoa(unsigned int value, char s[]) { + int i = 8; + int ptr = 0; + while (i-- > 0) { + s[ptr++] = "0123456789abcdef"[(value>>(i*4))&0xf]; + } + s[ptr] = 0; +} + + +/* errno.h stuff */ +int errno = 0; \ No newline at end of file diff --git a/kernel/klibc.h b/kernel/klibc.h new file mode 100755 index 0000000..cd0c4c6 --- /dev/null +++ b/kernel/klibc.h @@ -0,0 +1,125 @@ +/* Various typedefs -- some are x86-specific */ +#define CUSTOM_INTTYPES + +#define outb(port,value) __asm__ __volatile__ ("outb %%al,%%dx"::"d" (port), "a" (value)); +#define outbp(port,value) __asm __volatile__ ("outb %%al,%%dx; jmp 1f; 1:"::"d" (port), "a" (value)); +#define inb(port) ({unsigned char _v; __asm__ __volatile__ ("inb %%dx,%%al" : "=a" (_v) : "d" (port)); _v; }) + + +/* Various defines */ +#define NULL ((void *)0) +#define EOF (-1) +#define BUFSIZ 4096 +#define RAND_MAX ((unsigned int)0x8000000) +#define INT_MAX ((int)0x7fffffff) +#define M_PI 3.14159265358979323846 +#define __BYTE_ORDER 1 +#define __BIG_ENDIAN 2 + +typedef unsigned char u8; +typedef unsigned short u16; +typedef unsigned int u32; +typedef unsigned long int u64; + +#ifndef size_t +typedef unsigned int size_t; +#endif +typedef struct file +{ + void *mem; +} FILE; + +struct timeval { + int tv_sec; + int tv_usec; +}; + +struct timezone { + int tz_minuteswest; + int tz_dsttime; +}; + +/* stdlib.h functions */ +void *malloc(size_t size); +void free(void *ptr); +void *realloc(void *ptr, size_t size); +char *getenv(const char *name); +int rand(void); +int abs(int j); +void exit(int status); +void srand(unsigned int s); +int atexit(void (*function)(void)); +FILE *stdin, *stdout, *stderr; + +/* string.h functions */ +void *memset(void *s, int c, size_t n); +void *memcpy(void *dest, const void *src, size_t n); +void *memmove(void *dest, const void *src, size_t n); +size_t strlen(const char *s); +int strcmp(const char *s1, const char *s2); +int strcasecmp(const char *s1, const char *s2); +int memcmp(const void *s1, const void *s2, size_t n); +char *strdup(const char *s); +char *strchr(const char *s, int c); + +/* stdarg.h functions */ +typedef void * va_list; +#define va_start(v,a) v = (void *)((uintptr_t)(&a) + sizeof(a)) +#define va_end(v) +int vsnprintf(char *str, size_t size, const char *format, va_list ap); +/* va_arg*/ +#define args_list char * +#define _arg_stack_size(type) (((sizeof(type)-1)/sizeof(int)+1)*sizeof(int)) +#define args_start(ap, fmt) do { \ +ap = (char *)((unsigned int)&fmt + _arg_stack_size(&fmt)); \ +} while (0) +#define args_end(ap) +#define args_next(ap, type) (((type *)(ap+=_arg_stack_size(type)))[-1]) + +/* stdio.h functions */ +FILE *fopen(const char *path, const char *mode); +int feof(FILE *stream); +char *fgets(char *s, int size, FILE *stream); +size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream); +int fclose(FILE *fp); + +int printf(const char *format, ...); + +int fprintf(FILE *stream, const char *format, ...); +int fflush(FILE *stream); +int sprintf(char *str, const char *format, ...); +int sscanf(const char *str, const char *format, ...); +void itoa(int n, char s[]); + +void clearscreen(void); + +/* unistd.h functions */ +void usleep(unsigned long usec); +void sleep(unsigned long sec); +int getpid(void); + +/* time.h functions */ +u64 rdtsc(void); +int gettimeofday(struct timeval *tv, struct timezone *tz); +int time(void *); + +/* math.h functions */ +double cos(double x); +double sin(double x); +double sqrt(double x); + +/* errno.h functions */ +#define ENOENT 2 /* No such file or directory */ +#define ENOMEM 12 /* Out of memory */ +#define EBUSY 16 /* Device or resource busy */ +#define ENODEV 19 /* No such device */ +#define EINVAL 22 /* Invalid argument */ +#define ENOTTY 25 /* Not a typewriter */ +#define ENOSYS 38 /* Function not implemented */ +extern int errno; + +/* arpa/inet.h functions */ +unsigned int htonl(unsigned int hostlong); +unsigned short htons(unsigned short hostlong); + +void print(char *str); diff --git a/kernel/multiboot.S b/kernel/multiboot.S deleted file mode 100644 index d0a4fea..0000000 --- a/kernel/multiboot.S +++ /dev/null @@ -1,73 +0,0 @@ -/* boot.S - bootstrap the kernel */ -/* Copyright (C) 1999 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ - -#define ASM 1 -#include - - .text - - .code32 - .globl start, _start - - /* This entry is not used actually. */ -start: -_start: - jmp multiboot_entry - - /* Align 32 bits boundary. */ - .align 4 - - /* Multiboot header. */ -multiboot_header: - /* magic */ - .long MULTIBOOT_HEADER_MAGIC - /* flags */ - .long MULTIBOOT_HEADER_FLAGS - /* checksum */ - .long -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS) - /* header_addr */ - .long multiboot_header - /* load_addr */ - .long _start - /* load_end_addr */ - .long _edata - /* bss_end_addr */ - .long _end - /* entry_addr */ - .long multiboot_entry - -multiboot_entry: - /* Initialize the stack pointer. */ - movl $(stack + STACK_SIZE), %esp - - /* Reset EFLAGS. */ - pushl $0 - popf - - /* Push the pointer to the Multiboot information structure. */ - pushl %ebx - /* Push the magic value. */ - pushl %eax - - /* Now enter the C main function... */ - call EXT_C(cmain) - -loop: hlt - jmp loop - - /* Our stack area. */ - .comm stack, STACK_SIZE