@@ -308,7 +308,7 @@ fi | |||||
if test "${enable_vga}" = "yes"; then | if test "${enable_vga}" = "yes"; then | ||||
ac_cv_my_have_vga="yes" | 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" | CFLAGS="${CFLAGS} -fno-builtin -O2 -Wall -fno-stack-protector" | ||||
CCASFLAGS="${CCASFLAGS} -I. -fno-stack-protector" | CCASFLAGS="${CCASFLAGS} -I. -fno-stack-protector" | ||||
LDFLAGS="${LDFLAGS} -nostdlib -Wl,-N -Wl,-Ttext -Wl,100000 -fno-stack-protector" | LDFLAGS="${LDFLAGS} -nostdlib -Wl,-N -Wl,-Ttext -Wl,100000 -fno-stack-protector" | ||||
@@ -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 |
@@ -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"); | |||||
} | |||||
@@ -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<IDTSIZE;i++) { | |||||
init_idt_desc((u32)default_int, 0x08, INTGATE, &desc); | |||||
add_idt_desc(desc); | |||||
} | |||||
init_idt_desc((u32)k_int0, 0x08, INTGATE, &kidt[0]); | |||||
init_idt_desc((u32)k_int1, 0x08, INTGATE, &kidt[1]); | |||||
init_idt_desc((u32)k_int2, 0x08, INTGATE, &kidt[2]); | |||||
init_idt_desc((u32)k_int3, 0x08, INTGATE, &kidt[3]); | |||||
init_idt_desc((u32)k_int4, 0x08, INTGATE, &kidt[4]); | |||||
init_idt_desc((u32)k_int5, 0x08, INTGATE, &kidt[5]); | |||||
init_idt_desc((u32)k_int6, 0x08, INTGATE, &kidt[6]); | |||||
init_idt_desc((u32)k_int7, 0x08, INTGATE, &kidt[7]); | |||||
init_idt_desc((u32)k_int8, 0x08, INTGATE, &kidt[8]); | |||||
init_idt_desc((u32)k_int9, 0x08, INTGATE, &kidt[9]); | |||||
init_idt_desc((u32)k_int10, 0x08, INTGATE, &kidt[10]); | |||||
init_idt_desc((u32)k_int11, 0x08, INTGATE, &kidt[11]); | |||||
init_idt_desc((u32)k_int12, 0x08, INTGATE, &kidt[12]); | |||||
init_idt_desc((u32)k_int13, 0x08, INTGATE, &kidt[13]); | |||||
init_idt_desc((u32)k_int14, 0x08, INTGATE, &kidt[14]); | |||||
init_idt_desc((u32)k_int15, 0x08, INTGATE, &kidt[15]); | |||||
init_idt_desc((u32)k_int16, 0x08, INTGATE, &kidt[16]); | |||||
init_idt_desc((u32)k_int17, 0x08, INTGATE, &kidt[17]); | |||||
init_idt_desc((u32)k_int18, 0x08, INTGATE, &kidt[18]); | |||||
init_idt_desc((u32)k_irq0, 0x08, INTGATE, &kidt[32]); | |||||
init_idt_desc((u32)k_irq1, 0x08, INTGATE, &kidt[33]); | |||||
init_idt_desc((u32)k_irq2, 0x08, INTGATE, &kidt[34]); | |||||
init_idt_desc((u32)k_irq3, 0x08, INTGATE, &kidt[35]); | |||||
init_idt_desc((u32)k_irq4, 0x08, INTGATE, &kidt[36]); | |||||
init_idt_desc((u32)k_irq5, 0x08, INTGATE, &kidt[37]); | |||||
init_idt_desc((u32)k_irq6, 0x08, INTGATE, &kidt[38]); | |||||
init_idt_desc((u32)k_irq7, 0x08, INTGATE, &kidt[39]); | |||||
init_idt_desc((u32)k_irq8, 0x08, INTGATE, &kidt[40]); | |||||
kidtr.limite = IDTSIZE*8; | |||||
kidtr.base = IDTBASE; | |||||
memcpy((void*)kidtr.base, kidt, kidtr.limite); | |||||
#define printf(format, ...) { char __str[255]; sprintf (__str, format, __VA_ARGS__); print(__str);} | |||||
printf("Loading IDT from 0x%x\n", kidtr); | |||||
#undef printf | |||||
asm("lidtl (kidtr)"); | |||||
} |
@@ -0,0 +1,147 @@ | |||||
extern idt_default_int,idt_int0, idt_int1, idt_int2, idt_int3, idt_int4, idt_int5, idt_int6, idt_int7, idt_int8, idt_int9, idt_int10, idt_int11, idt_int12, idt_int13, idt_int14, idt_int15, idt_int16, idt_int17, idt_int18, idt_irq0, kbd_int, idt_irq2, idt_irq3, idt_irq4, idt_irq5, idt_irq6, idt_irq7, idt_irq8 | |||||
global default_int, k_int0, k_int1, k_int2, k_int3, k_int4, k_int5, k_int6, k_int7, k_int8, k_int9, k_int10, k_int11, k_int12, k_int13, k_int14, k_int15, k_int16, k_int17, k_int18, k_irq0, k_irq1, k_irq2, k_irq3, k_irq4, k_irq5, k_irq6, k_irq7, k_irq8 | |||||
default_int: | |||||
call idt_default_int ; Call C function | |||||
mov al,0x20 ; End Of Interruption | |||||
out 0x20,al ; Send EOI to PIC | |||||
iret | |||||
k_int0: | |||||
call idt_int0 | |||||
mov al,0x20 | |||||
out 0x20,al | |||||
iret | |||||
k_int1: | |||||
call idt_int1 | |||||
mov al,0x20 | |||||
out 0x20,al | |||||
iret | |||||
k_int2: | |||||
call idt_int2 | |||||
mov al,0x20 | |||||
out 0x20,al | |||||
iret | |||||
k_int3: | |||||
call idt_int3 | |||||
mov al,0x20 | |||||
out 0x20,al | |||||
iret | |||||
k_int4: | |||||
call idt_int4 | |||||
mov al,0x20 | |||||
out 0x20,al | |||||
iret | |||||
k_int5: | |||||
call idt_int5 | |||||
mov al,0x20 | |||||
out 0x20,al | |||||
iret | |||||
k_int6: | |||||
call idt_int6 | |||||
mov al,0x20 | |||||
out 0x20,al | |||||
iret | |||||
k_int7: | |||||
call idt_int7 | |||||
mov al,0x20 | |||||
out 0x20,al | |||||
iret | |||||
k_int8: | |||||
call idt_int8 | |||||
mov al,0x20 | |||||
out 0x20,al | |||||
iret | |||||
k_int9: | |||||
call idt_int9 | |||||
mov al,0x20 | |||||
out 0x20,al | |||||
iret | |||||
k_int10: | |||||
call idt_int10 | |||||
mov al,0x20 | |||||
out 0x20,al | |||||
iret | |||||
k_int11: | |||||
call idt_int11 | |||||
mov al,0x20 | |||||
out 0x20,al | |||||
iret | |||||
k_int12: | |||||
call idt_int12 | |||||
mov al,0x20 | |||||
out 0x20,al | |||||
iret | |||||
k_int13: | |||||
call idt_int13 | |||||
mov al,0x20 | |||||
out 0x20,al | |||||
iret | |||||
k_int14: | |||||
call idt_int14 | |||||
mov al,0x20 | |||||
out 0x20,al | |||||
iret | |||||
k_int15: | |||||
call idt_int15 | |||||
mov al,0x20 | |||||
out 0x20,al | |||||
iret | |||||
k_int16: | |||||
call idt_int16 | |||||
mov al,0x20 | |||||
out 0x20,al | |||||
iret | |||||
k_int17: | |||||
call idt_int17 | |||||
mov al,0x20 | |||||
out 0x20,al | |||||
iret | |||||
k_int18: | |||||
call idt_int18 | |||||
mov al,0x20 | |||||
out 0x20,al | |||||
iret | |||||
k_irq0: | |||||
call idt_irq0 | |||||
mov al,0x20 | |||||
out 0x20,al | |||||
iret | |||||
k_irq1: | |||||
call kbd_int | |||||
mov al,0x20 | |||||
out 0x20,al | |||||
iret | |||||
k_irq2: | |||||
call idt_irq2 | |||||
mov al,0x20 | |||||
out 0x20,al | |||||
iret | |||||
k_irq3: | |||||
call idt_irq3 | |||||
mov al,0x20 | |||||
out 0x20,al | |||||
iret | |||||
k_irq4: | |||||
call idt_irq4 | |||||
mov al,0x20 | |||||
out 0x20,al | |||||
iret | |||||
k_irq5: | |||||
call idt_irq5 | |||||
mov al,0x20 | |||||
out 0x20,al | |||||
iret | |||||
k_irq6: | |||||
call idt_irq6 | |||||
mov al,0x20 | |||||
out 0x20,al | |||||
iret | |||||
k_irq7: | |||||
call idt_irq7 | |||||
mov al,0x20 | |||||
out 0x20,al | |||||
iret | |||||
k_irq8: | |||||
call idt_irq8 | |||||
mov al,0x20 | |||||
out 0x20,al | |||||
iret |
@@ -0,0 +1,112 @@ | |||||
#include "kernel.h" | |||||
#include "klibc.h" | |||||
#include "drivers/timer.h" | |||||
void idt_default_int(void) { | |||||
print("!! Unknown interrupt\n"); | |||||
} | |||||
void idt_int0(void) { | |||||
print("!! Divide by 0\n "); | |||||
} | |||||
void idt_int1(void) { | |||||
print("!! Debug exception "); | |||||
} | |||||
void idt_int2(void) { | |||||
print("!! NMI "); | |||||
} | |||||
void idt_int3(void) { | |||||
print("!! Breakpoint "); | |||||
} | |||||
void idt_int4(void) { | |||||
print("!! Overflow "); | |||||
} | |||||
void idt_int5(void) { | |||||
print("!! BoundCheck "); | |||||
} | |||||
void idt_int6(void) { | |||||
print("!! Invalid Opcode "); | |||||
} | |||||
void idt_int7(void) { | |||||
print("!! Coprocessor not available "); | |||||
} | |||||
void idt_int8(void) { | |||||
print("!! Double Fault "); | |||||
} | |||||
void idt_int9(void) { | |||||
print("!! Coprocessor segment overrun "); | |||||
} | |||||
void idt_int10(void) { | |||||
print("!! Invalid TSS "); | |||||
} | |||||
void idt_int11(void) { | |||||
print("!! Segment not present "); | |||||
} | |||||
void idt_int12(void) { | |||||
print("!! Stack exception "); | |||||
} | |||||
void idt_int13(void) { | |||||
print("!! General protection exception "); | |||||
} | |||||
void idt_int14(void) { | |||||
print("!! Page fault "); | |||||
} | |||||
void idt_int15(void) { | |||||
print("!! Intel reserved int "); | |||||
} | |||||
void idt_int16(void) { | |||||
print("!! Coprocessor error "); | |||||
} | |||||
void idt_int17(void) { | |||||
print("!! Intel reserved (2) "); | |||||
} | |||||
void idt_int18(void) { | |||||
print("i18 "); | |||||
} | |||||
/* Used by Channel0 timer */ | |||||
void idt_irq0(void) { | |||||
ticks++; | |||||
} | |||||
void idt_irq2(void) { | |||||
print("IRQ 2"); | |||||
} | |||||
void idt_irq3(void) { | |||||
print("IRQ 3"); | |||||
} | |||||
void idt_irq4(void) { | |||||
print("IRQ 4"); | |||||
} | |||||
void idt_irq5(void) { | |||||
print("IRQ 5"); | |||||
} | |||||
void idt_irq6(void) { | |||||
print("IRQ 6"); | |||||
} | |||||
void idt_irq7(void) { | |||||
print("IRQ 7"); | |||||
} | |||||
void idt_irq8(void) { | |||||
print("IRQ 8"); | |||||
} | |||||
extern unsigned char kbdmap[]; | |||||
/* Keyboard irq is 1 */ | |||||
void kbd_int(void) { | |||||
unsigned char i; | |||||
do { | |||||
i=inb(0x64); | |||||
} while((i & 0x01) == 0); | |||||
i=inb(0x60); | |||||
i--; | |||||
if(i<0x80){ | |||||
putcar(kbdmap[i*4]); | |||||
} | |||||
} | |||||
@@ -0,0 +1,73 @@ | |||||
#include "klibc.h" | |||||
#define PIC_MASTER_ICW1 0x20 | |||||
#define PIC_MASTER_ICW2 0x21 | |||||
#define PIC_SLAVE_ICW1 0xA0 | |||||
#define PIC_SLAVE_ICW2 0xA1 | |||||
void init_pic(void) | |||||
{ | |||||
/* MASTER */ | |||||
outbp(PIC_MASTER_ICW1,0x11); // Init 8259A-1 | |||||
/* ICW2 - start vector = 32 */ | |||||
outbp(PIC_MASTER_ICW2,0x20); // IRQ 0-7 mapped to 0x20-0x27 | |||||
/* IICW3 */ | |||||
outbp(PIC_MASTER_ICW2,0x04); // 8259A-1 has slave | |||||
/* ICW4 */ | |||||
outbp(PIC_MASTER_ICW2,0x01); | |||||
/* Int mask */ | |||||
outbp(PIC_MASTER_ICW2,0xFF); | |||||
/* SLAVE */ | |||||
outbp(PIC_SLAVE_ICW1,0x11); | |||||
/* ICW2 - start vector = 96 */ | |||||
outbp(PIC_SLAVE_ICW2,0x70); | |||||
/* ICW3 */ | |||||
outbp(PIC_SLAVE_ICW2,0x02); | |||||
/* ICW4 */ | |||||
outbp(PIC_SLAVE_ICW2,0x01); | |||||
/* Int Mask */ | |||||
outbp(PIC_SLAVE_ICW2,0xFF); | |||||
/* Unmask irqs */ | |||||
outbp(0x21,0xFD); | |||||
} | |||||
static unsigned int cached_irq_mask = 0xffff; | |||||
#define __byte(x,y) (((unsigned char *)&(y))[x]) | |||||
#define cached_21 (__byte(0,cached_irq_mask)) | |||||
#define cached_A1 (__byte(1,cached_irq_mask)) | |||||
void disable_interrupt(char irq) | |||||
{ | |||||
unsigned int mask = 1 << irq; | |||||
cached_irq_mask |= mask; | |||||
if (irq & 8) { | |||||
outb(0xA1, cached_A1); | |||||
} else { | |||||
outb(0x21, cached_21); | |||||
} | |||||
} | |||||
void enable_interrupt(char irq) | |||||
{ | |||||
unsigned int mask = ~(1 << irq); | |||||
cached_irq_mask &= mask; | |||||
if (irq & 8) { | |||||
outb(0xA1, cached_A1); | |||||
} else { | |||||
outb(0x21, cached_21); | |||||
} | |||||
} | |||||
@@ -0,0 +1,30 @@ | |||||
#include "kernel.h" | |||||
#include "klibc.h" | |||||
extern int kmain(void); | |||||
/* Entry point | |||||
* bootsect.asm loaded this file at 0x0100:0x0, which is mapped | |||||
* at 0x8:0x1000 (selector+8bytes, offset 1000 (0x100 + 0x0) | |||||
*/ | |||||
/* 0x1000 */ | |||||
void _start(void) { | |||||
clearscreen(); | |||||
init_gdt(); | |||||
print("Loading IDT\n"); | |||||
init_idt(); | |||||
print("Loading PIC\n"); | |||||
init_pic(); | |||||
print("Running kmain()\n"); | |||||
sti; | |||||
kmain(); /* Call kernel's kmain() */ | |||||
while(1) { /* Never return */ | |||||
print("hlt;\n"); | |||||
} | |||||
} | |||||
@@ -0,0 +1 @@ | |||||
extern int _start(void); |
@@ -0,0 +1,56 @@ | |||||
#include "kernel.h" | |||||
#include "klibc.h" | |||||
#include "floppy.h" | |||||
int floppy_get_info(struct floppy_info *floppy_info) | |||||
{ | |||||
outb(0x70, 0x10); | |||||
unsigned char c = inb(0x71); | |||||
int a = c >> 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; | |||||
} |
@@ -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); |
@@ -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) */ | |||||
}; |
@@ -0,0 +1,4 @@ | |||||
#include "kernel.h" | |||||
#include "klibc.h" | |||||
#include "memory.h" | |||||
@@ -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); | |||||
} |
@@ -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); |
@@ -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 */ | |||||
} |
@@ -0,0 +1,2 @@ | |||||
extern u32 ticks; | |||||
void timer_phase(int hz); |
@@ -1,8 +1,8 @@ | |||||
/* | |||||
* libcaca Canvas for ultrafast compositing of Unicode letters | |||||
/* | |||||
* libcaca | |||||
* libcaca Colour ASCII-Art library | * libcaca Colour ASCII-Art library | ||||
* Copyright (c) 2006 Sam Hocevar <sam@hocevar.net> | |||||
* 2006 Jean-Yves Lamoureux <jylam@lnxscene.org> | |||||
* Copyright (c) 2006 Sam Hocevar <sam@zoy.org> | |||||
* 2006-2009 Jean-Yves Lamoureux <jylam@lnxscene.org> | |||||
* All Rights Reserved | * All Rights Reserved | ||||
* | * | ||||
* $Id$ | * $Id$ | ||||
@@ -14,388 +14,61 @@ | |||||
* http://sam.zoy.org/wtfpl/COPYING for more details. | * http://sam.zoy.org/wtfpl/COPYING for more details. | ||||
*/ | */ | ||||
/* | |||||
/* | |||||
* This file contains replacement functions for the standard C library | * This file contains replacement functions for the standard C library | ||||
* that must be used when building libcaca and libcaca into a kernel. | * that must be used when building libcaca and libcaca into a kernel. | ||||
*/ | */ | ||||
#include "config.h" | #include "config.h" | ||||
#include "caca_types.h" | #include "caca_types.h" | ||||
#ifdef __KERNEL__ | #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__ */ | #endif /* __KERNEL__ */ |
@@ -1,7 +1,7 @@ | |||||
/* | /* | ||||
* libcaca Canvas for ultrafast compositing of Unicode letters | * libcaca Canvas for ultrafast compositing of Unicode letters | ||||
* libcaca Colour ASCII-Art library | * libcaca Colour ASCII-Art library | ||||
* Copyright (c) 2006 Sam Hocevar <sam@hocevar.net> | |||||
* Copyright (c) 2006 Sam Hocevar <sam@zoy.org> | |||||
* All Rights Reserved | * All Rights Reserved | ||||
* | * | ||||
* $Id$ | * $Id$ | ||||
@@ -18,122 +18,24 @@ | |||||
* that must be used when building libcaca and libcaca into a kernel. | * 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 */ | /* The application's entry point */ | ||||
int main(int argc, char *argv[]); | 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); | |||||
@@ -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<j; i++, j--) { | |||||
c = s[i]; | |||||
s[i] = s[j]; | |||||
s[j] = c; | |||||
} | |||||
} | |||||
/* itoa implementation, by Kernighan and Ritchie's The C Programming Language */ | |||||
void itoa(int n, char s[]) | |||||
{ | |||||
int i, sign; | |||||
if ((sign = n) < 0) /* record sign */ | |||||
n = -n; /* make n positive */ | |||||
i = 0; | |||||
do { /* generate digits in reverse order */ | |||||
s[i++] = n % 10 + '0'; /* get next digit */ | |||||
} while ((n /= 10) > 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; |
@@ -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); |
@@ -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 <multiboot.h> | |||||
.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 |