initial commit
This commit is contained in:
commit
7ac42a5c9d
|
@ -0,0 +1 @@
|
|||
test.mp3
|
|
@ -0,0 +1,20 @@
|
|||
#!/bin/sh
|
||||
|
||||
# needs to be configured in boot.s as well
|
||||
LDADDR=0x100000
|
||||
BNAME=32.com
|
||||
|
||||
[ "$1" = "init" ] && for i in tool/*.c; do cc $i -O3 -o $(echo "$i" | sed 's/\.c$//') | true; done &&
|
||||
tool/genisr > include/isr.i
|
||||
|
||||
[ "$1" = "clean" ] && rm obj/* $BNAME
|
||||
|
||||
[ "$1" = "prog" ] && for i in src/*.s; do nasm -felf $i; done &&
|
||||
for i in src/*.c; do i386-elf-gcc -c $i -ffreestanding -Iinclude -Os | true; done &&
|
||||
mv *.o src/*.o obj &&
|
||||
i386-elf-ld -o obj/kernel -Ttext $LDADDR obj/entry.o $(ls obj/*.o | grep -v entry.o) --oformat binary &&
|
||||
cat obj/boot obj/kernel > $BNAME
|
||||
|
||||
[ -z "$1" ] && nasm boot/boot.s -o obj/boot | true && $0 prog | true
|
||||
|
||||
[ "$1" = "all" ] && ./b clean | true && ./b | true && dosbox-x $BNAME | true
|
|
@ -0,0 +1,119 @@
|
|||
[org 0x100]
|
||||
[bits 16]
|
||||
|
||||
cli
|
||||
mov ax, ds
|
||||
mov [torm+3], ax
|
||||
mov gs, ax
|
||||
mov [oldss], ss
|
||||
mov [oldsp], sp
|
||||
|
||||
in al, 0x92
|
||||
or al, 2
|
||||
out 0x92, al
|
||||
|
||||
; TODO maybe choose a better entrypoint than the start of hma
|
||||
cld
|
||||
mov cx, 65280-bindat
|
||||
mov si, bindat
|
||||
mov ax, 0xFFFF
|
||||
mov es, ax
|
||||
mov di, 0x10
|
||||
rep movsb
|
||||
|
||||
; relocate jump target
|
||||
xor eax, eax
|
||||
mov ax, ds
|
||||
shl eax, 4
|
||||
|
||||
add [gdt+2], eax
|
||||
add [gdt_end+2], eax
|
||||
|
||||
mov [gds+2], ax
|
||||
mov [gds16+2], ax
|
||||
mov [gcs16+2], ax
|
||||
shr eax, 16
|
||||
mov [gds+4], al
|
||||
mov [gds16+4], al
|
||||
mov [gcs16+4], al
|
||||
|
||||
lgdt [gdt]
|
||||
mov eax, cr0
|
||||
or al, 1
|
||||
mov cr0, eax
|
||||
ijmp: jmp dsseg:init
|
||||
|
||||
[bits 32]
|
||||
init:
|
||||
; retain stack pointer
|
||||
; esp = ebp = (ss << 4) + sp
|
||||
xor ebp, ebp
|
||||
xor ebx, ebx
|
||||
mov bp, ss
|
||||
mov bx, sp
|
||||
shl ebp, 4
|
||||
add ebp, ebx
|
||||
mov esp, ebp
|
||||
|
||||
mov ax, data
|
||||
mov ds, ax
|
||||
mov ss, ax
|
||||
mov es, ax
|
||||
mov fs, ax
|
||||
|
||||
call code:0x100000 ; start
|
||||
|
||||
cli
|
||||
jf: jmp cs16:in16
|
||||
|
||||
[bits 16]
|
||||
in16:
|
||||
mov ax, ds16
|
||||
mov ds, ax
|
||||
lidt [idt]
|
||||
|
||||
mov eax, cr0
|
||||
and al, 0xFE
|
||||
mov cr0, eax
|
||||
|
||||
torm: jmp 0:inrm
|
||||
|
||||
inrm: mov ax, gs
|
||||
mov ds, ax
|
||||
mov es, ax
|
||||
mov fs, ax
|
||||
mov ss, [oldss]
|
||||
mov sp, [oldsp]
|
||||
|
||||
sti
|
||||
xor ax, ax
|
||||
int 21h
|
||||
ret
|
||||
|
||||
idt: dw 0x3FF
|
||||
dd 0
|
||||
|
||||
gdt: dw gdt_end - gdt - 1
|
||||
dd gdt
|
||||
dw 0
|
||||
gcode: dd 0x0000ffff
|
||||
code equ gcode - gdt
|
||||
db 0, 10011011b, 11001111b, 0
|
||||
gdata: dd 0x0000ffff
|
||||
data equ gdata - gdt
|
||||
db 0, 10010011b, 11001111b, 0
|
||||
gds: dd 0x0000ffff
|
||||
dsseg equ gds - gdt
|
||||
db 0, 10011111b, 01001111b, 0
|
||||
gds16: dd 0x0000ffff
|
||||
ds16 equ gds16 - gdt
|
||||
db 0, 10010111b, 00001111b, 0
|
||||
gcs16: dd 0x0000ffff
|
||||
cs16 equ gcs16 - gdt
|
||||
db 0, 10011111b, 00001111b, 0
|
||||
gdt_end:
|
||||
|
||||
oldss: dw 0
|
||||
oldsp: dw 0
|
||||
|
||||
bindat equ $
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,23 @@
|
|||
#ifndef ALLOC
|
||||
#define ALLOC
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
typedef struct malloc_entry {
|
||||
void* ptr;
|
||||
uint32_t size;
|
||||
#define MALLOC_USED 1
|
||||
#define MALLOC_FREE 0
|
||||
uint8_t state;
|
||||
} __attribute__((packed)) malloc_entry;
|
||||
|
||||
void init_hashtable();
|
||||
void* malloc(uint32_t size);
|
||||
void free(void* ptr);
|
||||
void* realloc(void* ptr, uint32_t size);
|
||||
/*
|
||||
extern void* malloc_base_pointer;
|
||||
extern unsigned int highest_size;
|
||||
*/
|
||||
#endif
|
|
@ -0,0 +1,36 @@
|
|||
#ifndef ATA_PIO
|
||||
#define ATA_PIO
|
||||
#include <stdint.h>
|
||||
#include <ports.h>
|
||||
|
||||
// register stuff
|
||||
#define ATA_IO_BASE 0x1F0
|
||||
|
||||
#define ATA_CONTROL_BASE 0x3F0
|
||||
|
||||
#define ATA_SECONDARY_OFFSET 128
|
||||
|
||||
#define ATA_DATA_REGISTER 0
|
||||
#define ATA_ERROR_REGISTER 1
|
||||
#define ATA_FEATURES_REGISTER 1
|
||||
#define ATA_SECTOR_COUNT_REGISTER 2
|
||||
#define ATA_SECTOR_REGISTER 3
|
||||
#define ATA_CYL_LOW_REGISTER 4
|
||||
#define ATA_CYL_HIGH_REGISTER 5
|
||||
#define ATA_DRIVE_REGISTER 6
|
||||
#define ATA_STATUS_REGISTER 7
|
||||
#define ATA_COMMAND_REGISTER 7
|
||||
|
||||
#define ATA_ALTERNATE_STATUS_REGISTER 0
|
||||
#define ATA_DEVICE_CONTROL_REGISTER 0
|
||||
#define ATA_DRIVE_ADDRESS_REGISTER 1
|
||||
|
||||
// bitfield stuff
|
||||
|
||||
// declarations
|
||||
int ata_init(uint8_t bus, uint8_t drive);
|
||||
int ata_read(uint8_t bus, uint8_t drive, uint16_t* buf, uint16_t sectors, uint16_t lba_high, uint32_t lba_low);
|
||||
int ata_write(uint8_t bus, uint8_t drive, uint16_t* buf, uint16_t sectors, uint16_t lba_high, uint32_t lba_low);
|
||||
extern uint16_t ata_identify[256];
|
||||
|
||||
#endif
|
|
@ -0,0 +1,38 @@
|
|||
#ifndef INTERRUPT
|
||||
#define INTERRUPT
|
||||
|
||||
extern uint8_t isr_base[];
|
||||
|
||||
typedef struct {
|
||||
uint16_t lo;
|
||||
uint16_t sel;
|
||||
uint8_t reserved;
|
||||
uint8_t flags;
|
||||
uint16_t hi;
|
||||
} __attribute__((packed)) idt_gate;
|
||||
|
||||
typedef struct {
|
||||
uint16_t limit;
|
||||
idt_gate* base;
|
||||
} __attribute__((packed)) idtrc;
|
||||
|
||||
typedef struct {
|
||||
uint32_t ds;
|
||||
uint32_t edi, esi, ebp, uesp, ebx, edx, ecx, eax;
|
||||
uint32_t ino, err;
|
||||
uint32_t eip, cs, eflags, esp, ss;
|
||||
} registers;
|
||||
|
||||
extern idtrc idtr;
|
||||
extern idt_gate idt[256];
|
||||
|
||||
typedef void (*isr)(registers*);
|
||||
void regint(uint8_t ino, isr i);
|
||||
void set_idt(uint8_t n, uint32_t i);
|
||||
void lidt();
|
||||
void isr_init();
|
||||
void isr_handler(registers* r);
|
||||
void noint(registers* r);
|
||||
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,9 @@
|
|||
#ifndef KEYBOARD
|
||||
#define KEYBOARD
|
||||
#include <stdint.h>
|
||||
|
||||
extern uint8_t keys[256];
|
||||
|
||||
void kbmode(uint8_t mode);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,11 @@
|
|||
#ifndef PORTS
|
||||
#define PORTS
|
||||
#include <stdint.h>
|
||||
|
||||
uint8_t inb(uint16_t port);
|
||||
uint16_t inw(uint16_t port);
|
||||
|
||||
void outb(uint16_t port, uint8_t data);
|
||||
void outw(uint16_t port, uint16_t data);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,4 @@
|
|||
#ifndef STDDEF
|
||||
#define STDDEF
|
||||
#define NULL (void*)0
|
||||
#endif
|
|
@ -0,0 +1,7 @@
|
|||
#ifndef STDLIB
|
||||
#define STDLIB
|
||||
#include <stdint.h>
|
||||
|
||||
int abs(int i);
|
||||
char* itox(uint32_t x);
|
||||
#endif
|
|
@ -0,0 +1,9 @@
|
|||
#ifndef STRING
|
||||
#define STRING
|
||||
#include <stdint.h>
|
||||
|
||||
uint32_t strlen(char* str);
|
||||
void memcpy(uint8_t* dest, uint8_t* src, uint32_t len);
|
||||
void memset(uint8_t* dest, uint8_t set, uint32_t len);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,15 @@
|
|||
#ifndef VIDEO
|
||||
#define VIDEO
|
||||
|
||||
extern char* vga;
|
||||
|
||||
#define VGA_CCTRL 0x3d4
|
||||
#define VGA_CDATA 0x3d5
|
||||
#define ROWS 25
|
||||
#define COLS 80
|
||||
|
||||
void cls();
|
||||
void setcursor(unsigned int);
|
||||
int getcursor();
|
||||
|
||||
#endif
|
|
@ -0,0 +1,73 @@
|
|||
#include <alloc.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#define POINTER uint32_t
|
||||
#define BUCKET_NUM 256
|
||||
#define BUCKET_SIZE 6371
|
||||
|
||||
unsigned int highest_size = 0;
|
||||
// TODO determine this
|
||||
void* malloc_base_pointer = (void*) 0x01000000;
|
||||
#define table(BUCKET, SLOT) hashtable[(BUCKET*BUCKET_NUM)+SLOT]
|
||||
|
||||
malloc_entry* hashtable = (void*) 0x100000;
|
||||
|
||||
void init_hashtable() {
|
||||
memset((uint8_t*)hashtable, 0, 0xE00000);
|
||||
}
|
||||
|
||||
void* malloc(uint32_t size) {
|
||||
if(size == 0) return NULL;
|
||||
// TODO not hardcode this
|
||||
if(highest_size > 1073742000) return NULL;
|
||||
malloc_entry candidate_entry = (malloc_entry) {NULL, 0xFFFFFFFF, 0};
|
||||
int candidate_slot = 0xFFFFFF, foundpage = 0;
|
||||
if(size > highest_size) goto nocandidate;
|
||||
// TODO search more efficiently? maybe hashtable[0x10000][0x100]?
|
||||
// TODO combining nearby blocks
|
||||
// TODO if block is at highest pointer update hash table instead of reallocating
|
||||
for(int bi = 0; bi < 256; bi++) {
|
||||
for(int si = 0; si < BUCKET_SIZE; si++) {
|
||||
if(
|
||||
table(bi,si).state == MALLOC_FREE &&
|
||||
table(bi,si).size < candidate_entry.size &&
|
||||
table(bi,si).size >= size
|
||||
) {
|
||||
candidate_entry = table(bi,si);
|
||||
candidate_entry.size = size;
|
||||
// candidate_bucket = bi;
|
||||
candidate_slot = si;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(candidate_slot == 0xFFFFFF) {
|
||||
nocandidate:
|
||||
candidate_entry = (malloc_entry) {malloc_base_pointer + highest_size + 1, size, MALLOC_USED};
|
||||
highest_size += size;
|
||||
for(candidate_slot = 0; candidate_slot < BUCKET_SIZE; candidate_slot++) if(
|
||||
table((POINTER) candidate_entry.ptr & 0xFF,candidate_slot).ptr == NULL &&
|
||||
table((POINTER) candidate_entry.ptr & 0xFF,candidate_slot).state == 0
|
||||
) {foundpage = 1; break;}
|
||||
if(!foundpage) return NULL;
|
||||
} else candidate_entry.state = MALLOC_USED;
|
||||
table((POINTER) candidate_entry.ptr & 0xFF,candidate_slot) = candidate_entry;
|
||||
if(size > highest_size) highest_size = size;
|
||||
return candidate_entry.ptr;
|
||||
}
|
||||
|
||||
void free(void* ptr) {
|
||||
if(ptr != NULL) for(int i = 0; i < BUCKET_SIZE; i++) if(table((POINTER) ptr & 0xFF,i).ptr == ptr) {
|
||||
table((POINTER) ptr & 0xFF,i).state = MALLOC_FREE;
|
||||
}
|
||||
}
|
||||
|
||||
void* realloc(void* ptr, uint32_t size) {
|
||||
if(ptr != NULL) for(int i = 0; i < BUCKET_SIZE; i++) if(table((POINTER) ptr & 0xFF,i).ptr == ptr) {
|
||||
if(size <= table((POINTER) ptr & 0xFF,i).size) return ptr;
|
||||
free(ptr);
|
||||
void* newptr = malloc(size);
|
||||
memcpy(newptr, ptr, table((POINTER) ptr & 0xFF,i).size);
|
||||
return newptr;
|
||||
}
|
||||
return NULL;
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
#include <ata-pio.h>
|
||||
#include <video.h>
|
||||
|
||||
uint16_t ata_identify[256];
|
||||
// 0: disk is initialized
|
||||
// 1: no disks
|
||||
// 2: no disk on requested interface
|
||||
// 3: ATAPI
|
||||
int ata_init(uint8_t bus, uint8_t drive) {
|
||||
uint16_t io_base = ATA_IO_BASE - (bus ? ATA_SECONDARY_OFFSET : 0);
|
||||
if(inb(io_base + ATA_STATUS_REGISTER) == 0xFF) return 1;
|
||||
outb(io_base + ATA_DRIVE_REGISTER, drive ? 0xB0 : 0xA0);
|
||||
for(int i = 2; i < 6; i++) outb(io_base + i, 0);
|
||||
outb(io_base + ATA_STATUS_REGISTER, 0xEC);
|
||||
uint8_t status;
|
||||
do {
|
||||
status = inb(io_base + ATA_STATUS_REGISTER);
|
||||
if(!status) return 2;
|
||||
} while((status & 0x80));
|
||||
if(inb(io_base + 4) || inb(io_base + 5)) return 3;
|
||||
do {
|
||||
status = inb(io_base + ATA_STATUS_REGISTER);
|
||||
if(status & 1) return inb(io_base + ATA_ERROR_REGISTER);
|
||||
} while(!(status & 8));
|
||||
uint16_t err = inb(io_base + ATA_ERROR_REGISTER);
|
||||
if(err) return err;
|
||||
for(int i = 0; i < 256; i++) ata_identify[i] = inw(io_base);
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint16_t ata_setuprw(uint8_t bus, uint8_t drive, uint16_t sectors, uint16_t lba_high, uint32_t lba_low) {
|
||||
uint16_t io_base = ATA_IO_BASE - (bus ? ATA_SECONDARY_OFFSET : 0);
|
||||
outb(io_base + ATA_DRIVE_REGISTER, 0x40 | ((!!drive) << 4));
|
||||
uint8_t mports[4] = {2, 3, 4, 5};
|
||||
uint8_t dat[8] = {sectors >> 8, lba_low >> 24, lba_high >> 8, lba_high, sectors, lba_low, lba_low >> 8, lba_low >> 16};
|
||||
for(int i = 0; i < 8; i++) outb(io_base + mports[i % 4], dat[i]);
|
||||
return io_base;
|
||||
}
|
||||
|
||||
int ata_read(uint8_t bus, uint8_t drive, uint16_t* buf, uint16_t sectors, uint16_t lba_high, uint32_t lba_low) {
|
||||
uint16_t io_base = ata_setuprw(bus, drive, sectors, lba_high, lba_low);
|
||||
outb(io_base + ATA_COMMAND_REGISTER, 0x24);
|
||||
for(int i = 0; i < sectors * 256; i++) buf[i] = inw(io_base);
|
||||
}
|
||||
|
||||
int ata_write(uint8_t bus, uint8_t drive, uint16_t* buf, uint16_t sectors, uint16_t lba_high, uint32_t lba_low) {
|
||||
uint16_t io_base = ata_setuprw(bus, drive, sectors, lba_high, lba_low);
|
||||
outb(io_base + ATA_COMMAND_REGISTER, 0x34);
|
||||
for(int i = 0; i < sectors * 256; i++) outw(io_base, buf[i]);
|
||||
outb(io_base + ATA_COMMAND_REGISTER, 0xE7);
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
[bits 32]
|
||||
[extern entry]
|
||||
|
||||
global _start
|
||||
_start:
|
||||
call entry
|
||||
retf
|
|
@ -0,0 +1,28 @@
|
|||
[extern isr_handler]
|
||||
|
||||
global isr_base
|
||||
|
||||
isr: pusha
|
||||
mov ax, ds
|
||||
push eax
|
||||
mov ax, 0x10
|
||||
mov ds, ax
|
||||
mov es, ax
|
||||
mov fs, ax
|
||||
mov gs, ax
|
||||
push esp
|
||||
cld
|
||||
call isr_handler
|
||||
pop eax
|
||||
pop eax
|
||||
mov ds, ax
|
||||
mov es, ax
|
||||
mov fs, ax
|
||||
mov gs, ax
|
||||
popa
|
||||
add esp, 8
|
||||
sti
|
||||
iret
|
||||
|
||||
isr_base:
|
||||
%include "include/isr.i"
|
|
@ -0,0 +1,60 @@
|
|||
#include <ports.h>
|
||||
#include <interrupt.h>
|
||||
#include <video.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
idt_gate idt[256];
|
||||
idtrc idtr = {2047, idt}; // 256*8-1
|
||||
isr isrs[256];
|
||||
|
||||
void noint(registers* r) {
|
||||
*((uint16_t*)0xB8000) = 0x0F00 | r->ino;
|
||||
}
|
||||
|
||||
void set_idt(uint8_t n, uint32_t i) {
|
||||
idt[n].hi = (i >> 16) & 0xFFFF;
|
||||
idt[n].lo = i & 0xFFFF;
|
||||
idt[n].sel = 0x8; // TODO macro
|
||||
idt[n].flags = 0x8E;
|
||||
idt[n].reserved = 0;
|
||||
}
|
||||
|
||||
void lidt() {
|
||||
asm volatile("lidtl (%0)" : : "r" (&idtr));
|
||||
}
|
||||
|
||||
void isr_init() {
|
||||
|
||||
uint8_t portouts[20] = {
|
||||
0x20, 0x11,
|
||||
0xA0, 0x11,
|
||||
0x21, 0x20,
|
||||
0xA1, 0x28,
|
||||
0x21, 0x04,
|
||||
0xA1, 0x02,
|
||||
0x21, 0x01,
|
||||
0xA1, 0x01,
|
||||
0x21, 0x0,
|
||||
0xA1, 0x0
|
||||
};
|
||||
|
||||
for(int i = 0; i < 20; i+=2) outb(portouts[i], portouts[i+1]); // remap pic TODO undo function
|
||||
|
||||
for(int i = 0; i < 256; i++) { // TODO this can be done at compile time (even with relocation?)
|
||||
set_idt(i, ((uint32_t)isr_base) + (13*i));
|
||||
isrs[i] = noint;
|
||||
}
|
||||
|
||||
lidt();
|
||||
asm volatile("sti");
|
||||
}
|
||||
|
||||
void regint(uint8_t ino, isr i) {isrs[ino] = i;}
|
||||
|
||||
void isr_handler(registers* t){
|
||||
if(t->ino >= 32 && t->ino <= 47) { // from the pic
|
||||
if(t->ino >= 40) outb(0xA0, 0x20);
|
||||
outb(0x20, 0x20);
|
||||
}
|
||||
isrs[(uint8_t)t->ino](t);
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
#include <ports.h>
|
||||
#include <video.h>
|
||||
#include <keyboard.h>
|
||||
#include <interrupt.h>
|
||||
#include <ata-pio.h>
|
||||
#include <alloc.h>
|
||||
#include <video.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
uint32_t tick = 0;
|
||||
|
||||
void clock_update(registers* r) {
|
||||
tick++;
|
||||
for(int i = 0; i < 80 * 25; i++) {((uint16_t*)0xB8000)[i] = 0xF000 | (tick & 0xFF);}
|
||||
}
|
||||
|
||||
void setclock(uint32_t f) {
|
||||
uint32_t divisor = 1193182 / f;
|
||||
outb(0x43, 0x36);
|
||||
outb(0x40, divisor & 0xFF);
|
||||
outb(0x40, (divisor >> 8) & 0xFF);
|
||||
}
|
||||
|
||||
void entry() {
|
||||
isr_init();
|
||||
regint(32, clock_update);
|
||||
kbmode(1);
|
||||
setclock(8);
|
||||
|
||||
while(1) for(int i = 0; i < 80 * 25; i++) {
|
||||
((uint16_t*)0xB8000)[i] = 0xF000 | (tick & 0xFF);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
#include <video.h>
|
||||
#include <ports.h>
|
||||
#include <keyboard.h>
|
||||
#include <interrupt.h>
|
||||
|
||||
uint8_t keys[256];
|
||||
|
||||
void array_keyboard(registers* r) {
|
||||
// TODO ?????
|
||||
uint8_t scancode = inb(0x60);
|
||||
if(scancode > 0x39) keys[scancode-0x80] = 0;
|
||||
else keys[scancode] = 1;
|
||||
vga[44] = scancode;
|
||||
}
|
||||
|
||||
void no_keyboard(registers* r) {
|
||||
inb(0x60);
|
||||
}
|
||||
|
||||
void kbmode(uint8_t mode) {
|
||||
switch(mode) {
|
||||
case 0:
|
||||
// ignore keyboard
|
||||
regint(33, no_keyboard);
|
||||
break;
|
||||
case 1:
|
||||
// nonblocking, array based keyboard
|
||||
regint(33, array_keyboard);
|
||||
break;
|
||||
// TODO getc-like mode
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
#include <ports.h>
|
||||
|
||||
uint8_t inb(uint16_t port) {
|
||||
unsigned char result;
|
||||
asm("in %%dx, %%al" : "=a" (result) : "d" (port));
|
||||
return result;
|
||||
}
|
||||
|
||||
void outb(uint16_t port, uint8_t data) {
|
||||
asm("out %%al, %%dx" : : "a" (data), "d" (port));
|
||||
}
|
||||
|
||||
uint16_t inw(uint16_t port){
|
||||
uint16_t ret;
|
||||
asm volatile ("inw %1, %0" : "=a" (ret) : "dN" (port));
|
||||
return ret;
|
||||
}
|
||||
|
||||
void outw(uint16_t port, uint16_t data){
|
||||
asm volatile ("outw %1, %0" : : "dN" (port), "a" (data));
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
#include <stdlib.h>
|
||||
|
||||
int abs(int i) {
|
||||
return (i < 0) ? -i : i;
|
||||
}
|
||||
|
||||
char itoxret[8];
|
||||
char* itox(uint32_t x) {
|
||||
for(int i = 0; i < 8; i++) {
|
||||
itoxret[7-i] = (x >> (i*4)) & 0xF;
|
||||
itoxret[7-i] += (itoxret[7-i] > 9) ? ('A' - 10) : '0';
|
||||
}
|
||||
return itoxret;
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
#include <string.h>
|
||||
|
||||
uint32_t strlen(char* str) {
|
||||
uint32_t n = 0;
|
||||
while(*str++ != 0) n++;
|
||||
return n;
|
||||
}
|
||||
|
||||
void memcpy(uint8_t* dest, uint8_t* src, uint32_t len) {
|
||||
while(len-- > 0) *dest++ = *src++;
|
||||
}
|
||||
|
||||
void memset(uint8_t* dest, uint8_t set, uint32_t len) {
|
||||
while(len-- > 0) *dest++ = set;
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
#include <video.h>
|
||||
#include <ports.h>
|
||||
#include <string.h>
|
||||
|
||||
// start in 80x25 mode
|
||||
char* vga = (char*)0xB8000;
|
||||
|
||||
void cls() {
|
||||
for(int i; i < 2000; i++) vga[i*2] = ' ';
|
||||
setcursor(0);
|
||||
}
|
||||
|
||||
void setcursor(unsigned int i) {
|
||||
outb(VGA_CCTRL, 14);
|
||||
outb(VGA_CDATA, i >> 8);
|
||||
outb(VGA_CCTRL, 15);
|
||||
outb(VGA_CDATA, i & 0xff);
|
||||
}
|
||||
|
||||
int getcursor() {
|
||||
outb(VGA_CCTRL, 14);
|
||||
uint8_t ofs = inb(VGA_CDATA) << 8;
|
||||
outb(VGA_CCTRL, 15);
|
||||
ofs += inb(VGA_CDATA);
|
||||
return ofs;
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
#include <stdio.h>
|
||||
|
||||
// these exceptions have error codes
|
||||
const char ex[10] = {8, 10, 11, 12, 13, 14, 17, 21, 29, 30};
|
||||
|
||||
int main() {
|
||||
for(int i = 0; i < 256; i++) {
|
||||
int s = 0;
|
||||
for(int e = 0; e < 10; e++) if(i == ex[e]) {s = 1; break;}
|
||||
|
||||
printf("\ni%i: cli\n%spush dword strict %i\njmp strict near isr\n%s", i, s ? "" : "push byte 0\n", i, s ? "cs nop\n" : "");
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue