@@ -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" | |||
@@ -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 | |||
* 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 | |||
* | |||
* $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__ */ |
@@ -1,7 +1,7 @@ | |||
/* | |||
* libcaca Canvas for ultrafast compositing of Unicode letters | |||
* libcaca Colour ASCII-Art library | |||
* Copyright (c) 2006 Sam Hocevar <sam@hocevar.net> | |||
* Copyright (c) 2006 Sam Hocevar <sam@zoy.org> | |||
* 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); | |||
@@ -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 |