can read character from keyboard now
This commit is contained in:
@@ -1,19 +1,25 @@
|
||||
include ../*.inc
|
||||
SDIR ?= ../
|
||||
BDIR ?= ./
|
||||
|
||||
PROG=boot
|
||||
CSRCS= $(wildcard *.c)
|
||||
SSRCS= $(wildcard *.S)
|
||||
OBJS = $(SSRCS:.S=.o) $(CSRCS:.c=.o)
|
||||
PROG = boot
|
||||
SRCS = srt0.S gdt.S boot.c
|
||||
OBJS = srt0.o gdt.o boot.o
|
||||
|
||||
CFLAGS+=-c -fno-pie
|
||||
CPPFLAGS+=-nostdinc -DLOADADDR=$(LOADADDR) -DLINKADDR=$(LINKADDR) -DBOOTMAGIC=$(BOOTMAGIC)
|
||||
LDFLAGS+= -s -T ld.script -Ttext=$(LINKADDR) --no-omagic -M
|
||||
ESRCS = console.c print.c a20.c
|
||||
OBJS += $(ESRCS:.c=.o)
|
||||
|
||||
include $(SDIR)/Makefile.inc
|
||||
|
||||
CFLAGS += -no-pie
|
||||
CPPFLAGS += -DLOADADDR=$(LOADADDR) -DLINKADDR=$(LINKADDR) -DBOOTMAGIC=$(BOOTMAGIC) -DBOOTSTACKOFF=$(BOOTSTACKOFF)
|
||||
CPPFLAGS += -I $(SDIR)
|
||||
LDFLAGS += -s -Ttext=$(LINKADDR) -T ld.script --no-omagic -M
|
||||
|
||||
${PROG}: $(OBJS)
|
||||
@rm -f $(PROG)
|
||||
$(LD) $(LDFLAGS) -o $(BDIR)/$(PROG) $(OBJS)
|
||||
|
||||
$(OBJS): conf.h pio.h
|
||||
$(OBJS): $(SDIR)/u.h def.h dat.h fn.h
|
||||
|
||||
clean:
|
||||
rm -f $(PROG) $(PROG).bin *.o
|
||||
rm -f $(PROG) $(OBJS)
|
||||
|
||||
@@ -1,18 +1,7 @@
|
||||
#define elem(x) (sizeof(x)/sizeof((x)[0]))
|
||||
#include <u.h>
|
||||
#include "fn.h"
|
||||
|
||||
// IO Port Access Type Purpose
|
||||
// 0x60 Read/Write Data Port
|
||||
// 0x64 Read Status Register
|
||||
// 0x64 Write Command Register
|
||||
|
||||
typedef struct{
|
||||
char *name;
|
||||
void (**probes)(void);
|
||||
int cnt;
|
||||
}BootProbe;
|
||||
|
||||
// for high memory
|
||||
static void
|
||||
void
|
||||
a20up(void)
|
||||
{
|
||||
struct{
|
||||
@@ -43,25 +32,4 @@ a20up(void)
|
||||
;
|
||||
while(inb(i8042.sport) & i8042.dib)
|
||||
inb(i8042.dport);
|
||||
}
|
||||
|
||||
static void (*probe1[])(void) = {
|
||||
a20up,
|
||||
};
|
||||
static void (*probe2[])(void) = {
|
||||
};
|
||||
|
||||
static BootProbe probes[] = {
|
||||
{"probing", probe1, elem(probe1) },
|
||||
{"disk", probe2, elem(probe2) },
|
||||
};
|
||||
|
||||
static void
|
||||
machdep(void)
|
||||
{
|
||||
for(int i = 0; i < elem(probes); ++i){
|
||||
BootProbe bp = probes[i];
|
||||
for(int j = 0; j < bp.cnt; ++j)
|
||||
bp.probes[j]();
|
||||
}
|
||||
}
|
||||
}
|
||||
82
boot/boot.c
82
boot/boot.c
@@ -1,50 +1,58 @@
|
||||
#include <u.h>
|
||||
#include "dat.h"
|
||||
#include "fn.h"
|
||||
|
||||
typedef unsigned short u16;
|
||||
typedef unsigned char u8;
|
||||
typedef int dev_t;
|
||||
|
||||
#include "pio.h"
|
||||
#include "conf.h"
|
||||
void (*probe1[])(void) = {
|
||||
a20up,
|
||||
};
|
||||
void (*probe2[])(void) = {
|
||||
};
|
||||
|
||||
#define VGA_WIDTH 80
|
||||
#define VGA_LENGTH 25
|
||||
BootProbe probes[] = {
|
||||
{"probing", probe1, elem(probe1) },
|
||||
{"disk", probe2, elem(probe2) },
|
||||
};
|
||||
|
||||
char*
|
||||
memcpy(char *a, char *b, int l)
|
||||
ConDev condev = {
|
||||
.getc = pcgetc,
|
||||
.putc = pcputc,
|
||||
};
|
||||
|
||||
// https://wiki.osdev.org/BIOS
|
||||
void
|
||||
machdep(void)
|
||||
{
|
||||
for(int i = 0; i < l; ++i)
|
||||
a[i] = b[i];
|
||||
return a;
|
||||
for(int i = 0; i < elem(probes); ++i){
|
||||
BootProbe bp = probes[i];
|
||||
for(int j = 0; j < bp.cnt; ++j)
|
||||
bp.probes[j]();
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
strlen(char *s)
|
||||
static void
|
||||
puts(char *s)
|
||||
{
|
||||
int i = 0;
|
||||
for(; s[i]; ++i)
|
||||
;
|
||||
return i;
|
||||
}
|
||||
|
||||
char*
|
||||
itostr(int n, char *s)
|
||||
{
|
||||
char buf[16];
|
||||
char *p = buf;
|
||||
|
||||
do {
|
||||
*p++ = n%16;
|
||||
}while((n/=16) != 0);
|
||||
|
||||
while(p > buf){
|
||||
*s++ = "0123456789abcdef"[(int)*--p];
|
||||
}
|
||||
return s;
|
||||
for(;*s;++s)
|
||||
putchar(*s);
|
||||
}
|
||||
|
||||
void
|
||||
boot(dev_t bootdev)
|
||||
boot(int bootdev)
|
||||
{
|
||||
machdep();
|
||||
for(;;);
|
||||
char buf[8192];
|
||||
|
||||
machdep();
|
||||
putchar('\n');
|
||||
for(;;){
|
||||
int i=0, c=0;
|
||||
|
||||
puts("\nboot >> ");
|
||||
do{
|
||||
c = getchar();
|
||||
buf[i++] = c;
|
||||
}while(c != '\n' && i < sizeof(buf) - 1);
|
||||
buf[i-1] = 0;
|
||||
puts(buf);
|
||||
}
|
||||
}
|
||||
|
||||
26
boot/console.c
Normal file
26
boot/console.c
Normal file
@@ -0,0 +1,26 @@
|
||||
#include <u.h>
|
||||
#include "fn.h"
|
||||
|
||||
// https://stanislavs.org/helppc/int_16.html
|
||||
|
||||
void
|
||||
pcputc(int dev, int c)
|
||||
{
|
||||
__asm volatile("int $0x30" : : "a" (c | 0xe00), "b" (1) : "%ecx", "%edx", "cc" );
|
||||
}
|
||||
|
||||
int
|
||||
pcgetc(int dev)
|
||||
{
|
||||
register int rv;
|
||||
|
||||
// wait for available
|
||||
do{
|
||||
__asm volatile("int $0x36; setnz %b0" : "=a" (rv) :
|
||||
"0" (0x100) : "%ecx", "%edx", "cc" );
|
||||
}while((rv & 0xff) == 0);
|
||||
|
||||
__asm volatile("int $0x36" : "=a" (rv) :
|
||||
"0" (0x000) : "%ecx", "%edx", "cc" );
|
||||
return rv&0xff;
|
||||
}
|
||||
38
boot/dat.h
Normal file
38
boot/dat.h
Normal file
@@ -0,0 +1,38 @@
|
||||
// IO Port Access Type Purpose
|
||||
// 0x60 Read/Write Data Port
|
||||
// 0x64 Read Status Register
|
||||
// 0x64 Write Command Register
|
||||
|
||||
struct BIOSreg{
|
||||
u32 ax;
|
||||
u32 cx;
|
||||
u32 dx;
|
||||
u32 bx;
|
||||
u32 bp;
|
||||
u32 si;
|
||||
u32 di;
|
||||
u32 ds;
|
||||
u32 es;
|
||||
}__attribute__((packed));
|
||||
|
||||
|
||||
typedef struct{
|
||||
char *name;
|
||||
void (**probes)(void);
|
||||
int cnt;
|
||||
}BootProbe;
|
||||
|
||||
typedef struct{
|
||||
int (*getc)(int);
|
||||
void (*putc)(int, int);
|
||||
int dev;
|
||||
}ConDev;
|
||||
|
||||
// gdt.S
|
||||
extern volatile struct BIOSreg BIOSreg;
|
||||
|
||||
// boot.c
|
||||
extern void (*probe1[])(void);
|
||||
extern void (*probe2[])(void);
|
||||
extern BootProbe probes[];
|
||||
extern ConDev condev;
|
||||
47
boot/def.h
Normal file
47
boot/def.h
Normal file
@@ -0,0 +1,47 @@
|
||||
// Trap
|
||||
#define T_PRIVINFLT 0 /* privileged instruction */
|
||||
#define T_BPTFLT 1 /* breakpoint trap */
|
||||
#define T_ARITHTRAP 2 /* arithmetic trap */
|
||||
#define T_RESERVED 3 /* reserved fault base */
|
||||
#define T_PROTFLT 4 /* protection fault */
|
||||
#define T_TRCTRAP 5 /* trace trap */
|
||||
#define T_PAGEFLT 6 /* page fault */
|
||||
#define T_ALIGNFLT 7 /* alignment fault */
|
||||
#define T_DIVIDE 8 /* integer divide fault */
|
||||
#define T_NMI 9 /* non-maskable interrupt */
|
||||
#define T_OFLOW 10 /* overflow trap */
|
||||
#define T_BOUND 11 /* bounds check fault */
|
||||
#define T_DNA 12 /* device not available fault */
|
||||
#define T_DOUBLEFLT 13 /* double fault */
|
||||
#define T_FPOPFLT 14 /* fp coprocessor operand fetch fault (![P]Pro)*/
|
||||
#define T_TSSFLT 15 /* invalid tss fault */
|
||||
#define T_SEGNPFLT 16 /* segment not present fault */
|
||||
#define T_STKFLT 17 /* stack fault */
|
||||
#define T_MACHK 18 /* machine check ([P]Pro) */
|
||||
#define T_XFTRAP 19 /* SIMD FP exception */
|
||||
|
||||
/* memory segment types */
|
||||
#define SDT_MEMRO 16 /* memory read only */
|
||||
#define SDT_MEMROA 17 /* memory read only accessed */
|
||||
#define SDT_MEMRW 18 /* memory read write */
|
||||
#define SDT_MEMRWA 19 /* memory read write accessed */
|
||||
#define SDT_MEMROD 20 /* memory read only expand dwn limit */
|
||||
#define SDT_MEMRODA 21 /* memory read only expand dwn limit accessed */
|
||||
#define SDT_MEMRWD 22 /* memory read write expand dwn limit */
|
||||
#define SDT_MEMRWDA 23 /* memory read write expand dwn limit acessed */
|
||||
#define SDT_MEME 24 /* memory execute only */
|
||||
#define SDT_MEMEA 25 /* memory execute only accessed */
|
||||
#define SDT_MEMER 26 /* memory execute read */
|
||||
#define SDT_MEMERA 27 /* memory execute read accessed */
|
||||
#define SDT_MEMEC 28 /* memory execute only conforming */
|
||||
#define SDT_MEMEAC 29 /* memory execute only accessed conforming */
|
||||
#define SDT_MEMERC 30 /* memory execute read conforming */
|
||||
#define SDT_MEMERAC 31 /* memory execute read accessed conforming */
|
||||
|
||||
#define S16TEXT 0x18 // segment selector of text section
|
||||
#define S16DATA 0x20
|
||||
#define S32TEXT 0x08 // segment selector of text section
|
||||
#define S32DATA 0x10
|
||||
#define SDT_SYS386TGT 15 /* system 386 trap gate */
|
||||
|
||||
#define CR0_PE 0x01 // protected mode enable
|
||||
@@ -1,3 +1,15 @@
|
||||
|
||||
// console.c
|
||||
int pcgetc(int dev);
|
||||
void pcputc(int dev, int c);
|
||||
|
||||
// print.c
|
||||
void putchar(int c);
|
||||
int getchar(void);
|
||||
|
||||
// a20.c
|
||||
void a20up(void);
|
||||
|
||||
static __inline void
|
||||
outb(int port, u8 data)
|
||||
{
|
||||
@@ -11,4 +23,4 @@ inb(int port)
|
||||
|
||||
__asm volatile("inb %w1,%0" : "=a" (data) : "d" (port));
|
||||
return data;
|
||||
};
|
||||
}
|
||||
394
boot/gdt.S
394
boot/gdt.S
@@ -1,71 +1,95 @@
|
||||
.file "gdt.S"
|
||||
|
||||
// Trap
|
||||
#define T_PRIVINFLT 0 /* privileged instruction */
|
||||
#define T_BPTFLT 1 /* breakpoint trap */
|
||||
#define T_ARITHTRAP 2 /* arithmetic trap */
|
||||
#define T_RESERVED 3 /* reserved fault base */
|
||||
#define T_PROTFLT 4 /* protection fault */
|
||||
#define T_TRCTRAP 5 /* trace trap */
|
||||
#define T_PAGEFLT 6 /* page fault */
|
||||
#define T_ALIGNFLT 7 /* alignment fault */
|
||||
#define T_DIVIDE 8 /* integer divide fault */
|
||||
#define T_NMI 9 /* non-maskable interrupt */
|
||||
#define T_OFLOW 10 /* overflow trap */
|
||||
#define T_BOUND 11 /* bounds check fault */
|
||||
#define T_DNA 12 /* device not available fault */
|
||||
#define T_DOUBLEFLT 13 /* double fault */
|
||||
#define T_FPOPFLT 14 /* fp coprocessor operand fetch fault (![P]Pro)*/
|
||||
#define T_TSSFLT 15 /* invalid tss fault */
|
||||
#define T_SEGNPFLT 16 /* segment not present fault */
|
||||
#define T_STKFLT 17 /* stack fault */
|
||||
#define T_MACHK 18 /* machine check ([P]Pro) */
|
||||
#define T_XFTRAP 19 /* SIMD FP exception */
|
||||
#include "def.h"
|
||||
|
||||
/* memory segment types */
|
||||
#define SDT_MEMRO 16 /* memory read only */
|
||||
#define SDT_MEMROA 17 /* memory read only accessed */
|
||||
#define SDT_MEMRW 18 /* memory read write */
|
||||
#define SDT_MEMRWA 19 /* memory read write accessed */
|
||||
#define SDT_MEMROD 20 /* memory read only expand dwn limit */
|
||||
#define SDT_MEMRODA 21 /* memory read only expand dwn limit accessed */
|
||||
#define SDT_MEMRWD 22 /* memory read write expand dwn limit */
|
||||
#define SDT_MEMRWDA 23 /* memory read write expand dwn limit acessed */
|
||||
#define SDT_MEME 24 /* memory execute only */
|
||||
#define SDT_MEMEA 25 /* memory execute only accessed */
|
||||
#define SDT_MEMER 26 /* memory execute read */
|
||||
#define SDT_MEMERA 27 /* memory execute read accessed */
|
||||
#define SDT_MEMEC 28 /* memory execute only conforming */
|
||||
#define SDT_MEMEAC 29 /* memory execute only accessed conforming */
|
||||
#define SDT_MEMERC 30 /* memory execute read conforming */
|
||||
#define SDT_MEMERAC 31 /* memory execute read accessed conforming */
|
||||
#define GEN_LABEL(n) X##n
|
||||
|
||||
#define S32TEXT 0x08 // segment selector of text section
|
||||
#define SDT_SYS386TGT 15 /* system 386 trap gate */
|
||||
// idt entry
|
||||
#define idte(e) \
|
||||
movl $GEN_LABEL(e), %eax ; \
|
||||
call entry
|
||||
|
||||
#define IPROC(n) X##n
|
||||
#define idte(e) \
|
||||
movl $IPROC(e), %eax ; call entry_idt
|
||||
// idt bios entry
|
||||
#define idtbe(b) idte(emu##b)
|
||||
|
||||
#define IENTRY_ERR(name,err) \
|
||||
IPROC(name): \
|
||||
pushl $err ; \
|
||||
jmp 1f
|
||||
#define GEN_TRAP(name, err) \
|
||||
GEN_LABEL(name): \
|
||||
pushl $err; \
|
||||
jmp 1f
|
||||
|
||||
#define GEN_EMU(n) \
|
||||
GEN_LABEL(emu##n): \
|
||||
pushl $n; \
|
||||
jmp 1f
|
||||
|
||||
|
||||
#define prot2real \
|
||||
ljmp $S16TEXT, $1f - LINKADDR; \
|
||||
1: \
|
||||
.code16; \
|
||||
movw $S16DATA, %ax; \
|
||||
movw %ax, %ds; \
|
||||
movw %ax, %es; \
|
||||
\
|
||||
movl %cr0, %eax; \
|
||||
andl $~CR0_PE, %eax; \
|
||||
movl %eax, %cr0; \
|
||||
\
|
||||
data32 ljmp $(LINKADDR >> 4), $1f - LINKADDR; \
|
||||
1: \
|
||||
movw %cs, %ax; \
|
||||
movw %ax, %ds; \
|
||||
movw %ax, %es; \
|
||||
xorw %ax, %ax; \
|
||||
movw %ax, %ss; \
|
||||
data32 addr32 lidt (Idtr_real - LINKADDR);
|
||||
|
||||
#define real2prot \
|
||||
movw $LINKADDR >> 4, %ax; \
|
||||
movw %ax, %ds; \
|
||||
data32 addr32 lgdt (Gdtr - LINKADDR); \
|
||||
\
|
||||
movl %cr0, %eax; \
|
||||
orl $CR0_PE, %eax; \
|
||||
movl %eax, %cr0; \
|
||||
\
|
||||
data32 ljmp $S32TEXT, $1f; \
|
||||
1: \
|
||||
.code32; \
|
||||
mov $S32DATA, %eax; \
|
||||
mov %ax, %ds; \
|
||||
mov %ax, %ss; \
|
||||
mov %ax, %es; \
|
||||
\
|
||||
lidt Idtr;
|
||||
|
||||
.text
|
||||
.globl BIOSreg
|
||||
BIOSreg:
|
||||
BIOS_AX: .long 0
|
||||
BIOS_CX: .long 0
|
||||
BIOS_DX: .long 0
|
||||
BIOS_BX: .long 0
|
||||
BIOS_BP: .long 0
|
||||
BIOS_SI: .long 0
|
||||
BIOS_DI: .long 0
|
||||
BIOS_DS: .long 0
|
||||
BIOS_ES: .long 0
|
||||
|
||||
.text
|
||||
.code32
|
||||
.globl pmm_init
|
||||
.globl pmode_init
|
||||
|
||||
entry_idt:
|
||||
// Table
|
||||
// IDTR offset + 0 : entry 0
|
||||
// IDTR offset + 8 : entry 1
|
||||
//
|
||||
// IDTR offset + 0 : entry 0
|
||||
// IDTR offset + 8 : entry 1
|
||||
//
|
||||
// Gate Descriptor
|
||||
// 63 ~ 48 : offset low
|
||||
// 47 ~ 32 : info
|
||||
// 31 ~ 16 : segment selector
|
||||
// 15 ~ 0 : offset high
|
||||
// 63 ~ 48 : offset low
|
||||
// 47 ~ 32 : info
|
||||
// 31 ~ 16 : segment selector
|
||||
// 15 ~ 0 : offset high
|
||||
entry:
|
||||
movw %ax, (%ebx)
|
||||
movw $S32TEXT, 2(%ebx)
|
||||
movw $((0x80|SDT_SYS386TGT) << 8), 4(%ebx)
|
||||
@@ -74,8 +98,9 @@ entry_idt:
|
||||
addl $8, %ebx
|
||||
ret
|
||||
|
||||
// init IDT for protected mode
|
||||
.align 8, 0x90
|
||||
pmm_init:
|
||||
pmode_init:
|
||||
movl $idt, %ebx
|
||||
movl $Idtr, %eax
|
||||
movw $(640 - 1), (%eax)
|
||||
@@ -88,6 +113,15 @@ pmm_init:
|
||||
idte(xx); idte(xx); idte(xx); idte(xx); idte(xx); idte(xx)
|
||||
idte(xx); idte(xx); idte(xx); idte(xx); idte(xx); idte(xx)
|
||||
idte(xx)
|
||||
/* BIOS interrupt call (32-63) */
|
||||
idtbe(0); idtbe(1); idtbe(2); idtbe(3); idtbe(4); idtbe(5)
|
||||
idtbe(6); idtbe(7); idtbe(8); idtbe(9); idtbe(10); idtbe(11)
|
||||
idtbe(12); idtbe(13); idtbe(14); idtbe(15); idtbe(16); idtbe(17)
|
||||
idtbe(18); idtbe(19); idtbe(20); idtbe(21); idtbe(22); idtbe(23)
|
||||
idtbe(24); idtbe(25); idtbe(26); idtbe(27); idtbe(28); idtbe(29)
|
||||
idtbe(30); idtbe(31); idtbe(32); idtbe(33); idtbe(34); idtbe(35)
|
||||
idtbe(36); idtbe(37); idtbe(38); idtbe(39); idtbe(40); idtbe(41)
|
||||
idtbe(42); idtbe(43); idtbe(44); idtbe(45); idtbe(46); idtbe(47)
|
||||
|
||||
lidt Idtr
|
||||
ret
|
||||
@@ -105,86 +139,204 @@ Idtr:
|
||||
|
||||
.text
|
||||
.align 8
|
||||
gdt:
|
||||
/* 0x00 : null */
|
||||
.space 8
|
||||
/* 0x08 : flat code */
|
||||
.word 0xFFFF # lolimit
|
||||
.word 0 # lobase
|
||||
.byte 0 # midbase
|
||||
.byte SDT_MEMERAC | 0 | 0x80 # RXAC, dpl = 0, present
|
||||
.byte 0xf | 0 | 0x40 | 0x80 # hilimit, xx, 32bit, 4k granularity
|
||||
.byte 0 # hibase
|
||||
/* 0x10 : flat data */
|
||||
.word 0xFFFF # lolimit
|
||||
.word 0 # lobase
|
||||
.byte 0 # midbase
|
||||
.byte SDT_MEMRWA | 0 | 0x80 # RWA, dpl = 0, present
|
||||
.byte 0xf | 0 | 0x40 | 0x80 # hilimit, xx, 32bit, 4k granularity
|
||||
.byte 0 # hibase
|
||||
/* 0x18 : 16 bit code */
|
||||
.word 0xFFFF # lolimit
|
||||
.word (LINKADDR & 0xffff) # lobase
|
||||
.byte (LINKADDR >> 16) & 0xff # midbase
|
||||
.byte SDT_MEMERAC | 0 | 0x80 # RXAC, dpl = 0, present
|
||||
.byte 0x0 | 0 | 0 | 0 # hilimit, xx, 16bit, byte granularity
|
||||
.byte (LINKADDR >> 20) & 0xff # hibase
|
||||
/* 0x20 : 16 bit data */
|
||||
.word 0xFFFF # lolimit
|
||||
.word (LINKADDR & 0xffff) # lobase
|
||||
.byte (LINKADDR >> 16) & 0xff # midbase
|
||||
.byte SDT_MEMRWA | 0 | 0x80 # RWA, dpl = 0, present
|
||||
.byte 0x0 | 0 | 0 | 0 # hilimit, xx, 16bit, byte granularity
|
||||
.byte (LINKADDR >> 20) & 0xff # hibase
|
||||
.globl Idtr_real
|
||||
Idtr_real:
|
||||
.word 1023 // 256 entry, 1k
|
||||
.long 0
|
||||
.word 0
|
||||
|
||||
.align 8
|
||||
gdt:
|
||||
/* 0x00 : null */
|
||||
.space 8
|
||||
/* 0x08 : flat code */
|
||||
.word 0xFFFF // lolimit
|
||||
.word 0 // lobase
|
||||
.byte 0 // midbase
|
||||
.byte SDT_MEMERAC | 0 | 0x80 // RXAC, dpl = 0, present
|
||||
.byte 0xf | 0 | 0x40 | 0x80 // hilimit, xx, 32bit, 4k granularity
|
||||
.byte 0 // hibase
|
||||
/* 0x10 : flat data */
|
||||
.word 0xFFFF // lolimit
|
||||
.word 0 // lobase
|
||||
.byte 0 // midbase
|
||||
.byte SDT_MEMRWA | 0 | 0x80 // RWA, dpl = 0, present
|
||||
.byte 0xf | 0 | 0x40 | 0x80 // hilimit, xx, 32bit, 4k granularity
|
||||
.byte 0 // hibase
|
||||
/* 0x18 : 16 bit code */
|
||||
.word 0xFFFF // lolimit
|
||||
.word (LINKADDR & 0xffff) // lobase
|
||||
.byte (LINKADDR >> 16) & 0xff // midbase
|
||||
.byte SDT_MEMERAC | 0 | 0x80 // RXAC, dpl = 0, present
|
||||
.byte 0x0 | 0 | 0 | 0 // hilimit, xx, 16bit, byte granularity
|
||||
.byte (LINKADDR >> 20) & 0xff // hibase
|
||||
/* 0x20 : 16 bit data */
|
||||
.word 0xFFFF // lolimit
|
||||
.word (LINKADDR & 0xffff) // lobase
|
||||
.byte (LINKADDR >> 16) & 0xff // midbase
|
||||
.byte SDT_MEMRWA | 0 | 0x80 // RWA, dpl = 0, present
|
||||
.byte 0x0 | 0 | 0 | 0 // hilimit, xx, 16bit, byte granularity
|
||||
.byte (LINKADDR >> 20) & 0xff // hibase
|
||||
|
||||
|
||||
// Register GDT
|
||||
.globl Gdtr
|
||||
Gdtr:
|
||||
.word . - gdt -1
|
||||
.word . - gdt - 1
|
||||
.long gdt
|
||||
.word 0
|
||||
|
||||
// ENTRY Reserved
|
||||
IPROC(xx):
|
||||
GEN_LABEL(xx):
|
||||
pushl $1
|
||||
pushl $T_RESERVED
|
||||
jmp 1f
|
||||
|
||||
// trap entry points
|
||||
IENTRY_ERR(de,T_DIVIDE) /* #DE divide by zero */
|
||||
IENTRY_ERR(db,T_TRCTRAP) /* #DB debug */
|
||||
IENTRY_ERR(nmi,T_NMI) /* NMI */
|
||||
IENTRY_ERR(bp,T_BPTFLT) /* #BP breakpoint */
|
||||
IENTRY_ERR(of,T_OFLOW) /* #OF overflow */
|
||||
IENTRY_ERR(br,T_BOUND) /* #BR BOUND range exceeded */
|
||||
IENTRY_ERR(ud,T_PRIVINFLT) /* #UD invalid opcode */
|
||||
IENTRY_ERR(nm,T_DNA) /* #NM device not available */
|
||||
IENTRY_ERR(df,T_DOUBLEFLT) /* #DF double fault */
|
||||
IENTRY_ERR(fo,T_FPOPFLT) /* #FO coprocessor segment overrun */
|
||||
IENTRY_ERR(ts,T_TSSFLT) /* #TS invalid TSS */
|
||||
IENTRY_ERR(np,T_SEGNPFLT) /* #NP segment not present */
|
||||
IENTRY_ERR(ss,T_STKFLT) /* #SS stack fault */
|
||||
IENTRY_ERR(gp,T_PROTFLT) /* #GP general protection */
|
||||
IENTRY_ERR(pf,T_PAGEFLT) /* #PF page fault */
|
||||
IENTRY_ERR(mf,T_ARITHTRAP) /* #MF floating point error */
|
||||
IENTRY_ERR(ac,T_ALIGNFLT) /* #AC alignment check */
|
||||
IENTRY_ERR(mc,T_MACHK) /* #MC machine check */
|
||||
|
||||
GEN_TRAP(de,T_DIVIDE) /* DE divide by zero */
|
||||
GEN_TRAP(db,T_TRCTRAP) /* DB debug */
|
||||
GEN_TRAP(nmi,T_NMI) /* NMI */
|
||||
GEN_TRAP(bp,T_BPTFLT) /* BP breakpoint */
|
||||
GEN_TRAP(of,T_OFLOW) /* OF overflow */
|
||||
GEN_TRAP(br,T_BOUND) /* BR BOUND range exceeded */
|
||||
GEN_TRAP(ud,T_PRIVINFLT) /* UD invalid opcode */
|
||||
GEN_TRAP(nm,T_DNA) /* NM device not available */
|
||||
GEN_TRAP(df,T_DOUBLEFLT) /* DF double fault */
|
||||
GEN_TRAP(fo,T_FPOPFLT) /* FO coprocessor segment overrun */
|
||||
GEN_TRAP(ts,T_TSSFLT) /* TS invalid TSS */
|
||||
GEN_TRAP(np,T_SEGNPFLT) /* NP segment not present */
|
||||
GEN_TRAP(ss,T_STKFLT) /* SS stack fault */
|
||||
GEN_TRAP(gp,T_PROTFLT) /* GP general protection */
|
||||
GEN_TRAP(pf,T_PAGEFLT) /* PF page fault */
|
||||
GEN_TRAP(mf,T_ARITHTRAP) /* MF floating point error */
|
||||
GEN_TRAP(ac,T_ALIGNFLT) /* AC alignment check */
|
||||
GEN_TRAP(mc,T_MACHK) /* MC machine check */
|
||||
1:
|
||||
jmp alltraps
|
||||
|
||||
// in boot mode don't want handle trap
|
||||
alltraps:
|
||||
popl %ecx // what trap
|
||||
hlt
|
||||
iret
|
||||
jmp 1b
|
||||
|
||||
GEN_EMU(0); GEN_EMU(1); GEN_EMU(2); GEN_EMU(3)
|
||||
GEN_EMU(4); GEN_EMU(5); GEN_EMU(6); GEN_EMU(7)
|
||||
GEN_EMU(8); GEN_EMU(9); GEN_EMU(10); GEN_EMU(11)
|
||||
GEN_EMU(12); GEN_EMU(13); GEN_EMU(14); GEN_EMU(15)
|
||||
GEN_EMU(16); GEN_EMU(17); GEN_EMU(18); GEN_EMU(19)
|
||||
GEN_EMU(20); GEN_EMU(21); GEN_EMU(22); GEN_EMU(23)
|
||||
GEN_EMU(24); GEN_EMU(25); GEN_EMU(26); GEN_EMU(27)
|
||||
GEN_EMU(28); GEN_EMU(29); GEN_EMU(30); GEN_EMU(31)
|
||||
GEN_EMU(32); GEN_EMU(33); GEN_EMU(34); GEN_EMU(35)
|
||||
GEN_EMU(36); GEN_EMU(37); GEN_EMU(38); GEN_EMU(39)
|
||||
GEN_EMU(40); GEN_EMU(41); GEN_EMU(42); GEN_EMU(43)
|
||||
GEN_EMU(44); GEN_EMU(45); GEN_EMU(46); GEN_EMU(47)
|
||||
1: jmp EMUh
|
||||
|
||||
|
||||
// bios interrupt entry point
|
||||
// switch to real to protected mode and emulate 16bit mode
|
||||
|
||||
// switch to real to protected mode and emulate 16bit mode
|
||||
.globl EMUh
|
||||
.align 8, 0x90
|
||||
EMUh:
|
||||
pushl %eax
|
||||
EMUh: // build stack for real mode
|
||||
mov %eax, 5f // save number to code segment not in the data segment
|
||||
pop %eax
|
||||
|
||||
.end
|
||||
pusha
|
||||
push %ds
|
||||
push %es
|
||||
push %fs
|
||||
push %gs
|
||||
|
||||
movb %al, intno // save BIOS int vector
|
||||
|
||||
// BIOS_regs is area for saving the contents of registers returned by the BIOS during a BIOS CALL
|
||||
movl BIOS_ES, %eax
|
||||
movl $0x00, %eax
|
||||
mov %eax, 7f
|
||||
movl BIOS_DS, %eax
|
||||
movl $0x00, %eax
|
||||
mov %eax, 6f
|
||||
|
||||
prot2real
|
||||
|
||||
// save ds to stack and rewrite es, ds
|
||||
push %ds
|
||||
|
||||
// data32 movl $Leax, %eax
|
||||
.byte 0x66, 0xb8
|
||||
7: .long 0x90909090
|
||||
mov %ax, %es
|
||||
|
||||
// data32 movl $Leax, %eax
|
||||
.byte 0x66, 0xb8
|
||||
6: .long 0x90909090
|
||||
mov %ax, %ds
|
||||
|
||||
// data32 movl $Leax, %eax => now ax is holding interrupt nummber
|
||||
.byte 0x66, 0xb8
|
||||
5: .long 0x90909090
|
||||
|
||||
;sti
|
||||
int $0 // do interrupt
|
||||
intno = . -1;
|
||||
cli;
|
||||
|
||||
// restore register
|
||||
// preserve bx,es for protected mode
|
||||
pop %ds
|
||||
addr32 movl %eax, (2f - LINKADDR)
|
||||
movl %ebx, %eax
|
||||
addr32 movl %eax, (4f - LINKADDR)
|
||||
movl %es, %eax
|
||||
addr32 movl %eax, (3f- LINKADDR)
|
||||
addr32 movl (2f - LINKADDR), %eax
|
||||
|
||||
// save eflags to bh
|
||||
movb %ah, %bh
|
||||
lahf
|
||||
xchgb %ah, %bh
|
||||
|
||||
// preserve ax for protected mode
|
||||
addr32 movl %eax, (2f - LINKADDR)
|
||||
|
||||
real2prot
|
||||
|
||||
// movl $Leax, %eax
|
||||
.byte 0xb8
|
||||
4: .long 0x90909090
|
||||
mov %eax, BIOS_BX
|
||||
|
||||
// movl $Leax, %eax
|
||||
.byte 0xb8
|
||||
3: .long 0x90909090
|
||||
mov %eax, BIOS_ES
|
||||
|
||||
// movl $Leax, %eax
|
||||
.byte 0xb8
|
||||
2: .long 0x90909090
|
||||
|
||||
// pass BIOS return values back to caller
|
||||
movl %eax, 0xb*4(%esp)
|
||||
movl %ecx, 0xa*4(%esp)
|
||||
movl %edx, 0x9*4(%esp)
|
||||
movb %bh, 0xe*4(%esp) // restore eflags
|
||||
|
||||
// save register into BIOSREG
|
||||
.code32
|
||||
movl %eax, BIOS_AX
|
||||
movl %ecx, BIOS_CX
|
||||
movl %edx, BIOS_DX
|
||||
movl %ebp, BIOS_BP
|
||||
movl %esi, BIOS_SI
|
||||
movl %edi, BIOS_DI
|
||||
|
||||
// clear NT(Nested Task Flag: 14) flag in eflag
|
||||
// if 1 : interrupting
|
||||
pushf
|
||||
pop %eax
|
||||
and $0xffffbfff, %eax
|
||||
push %eax
|
||||
popf
|
||||
|
||||
pop %ds
|
||||
pop %es
|
||||
pop %fs
|
||||
pop %gs
|
||||
popa
|
||||
iret
|
||||
|
||||
@@ -1,27 +1,54 @@
|
||||
OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
|
||||
OUTPUT_ARCH(i386)
|
||||
|
||||
PHDRS
|
||||
PHDRS
|
||||
{
|
||||
text PT_LOAD;
|
||||
}
|
||||
SECTIONS
|
||||
{
|
||||
.text : {
|
||||
KEEP(srt0.o(.text))
|
||||
*(.text)
|
||||
} :text
|
||||
etext = .;
|
||||
.data : { *(.data) } :text
|
||||
.rodata : { *(.rodata) } :text
|
||||
edata = .;
|
||||
.bss : { *(.bss) } :text
|
||||
ebss = .;
|
||||
end = .;
|
||||
/DISCARD/ :
|
||||
.text :
|
||||
{
|
||||
start = . ;
|
||||
_start = . ;
|
||||
__start = . ;
|
||||
*(.text)
|
||||
etext = . ;
|
||||
} :text
|
||||
.data :
|
||||
{
|
||||
__data_start__ = . ;
|
||||
*(.data)
|
||||
__data_end__ = . ;
|
||||
__rdata_start__ = . ;
|
||||
*(.rdata)
|
||||
__rdata_end__ = . ;
|
||||
*(.pdata)
|
||||
*(.edata)
|
||||
} :text
|
||||
.bss :
|
||||
{
|
||||
edata = . ;
|
||||
_edata = . ;
|
||||
__edata = . ;
|
||||
__bss_start__ = . ;
|
||||
*(.bss)
|
||||
__common_start__ = . ;
|
||||
*(COMMON)
|
||||
__bss_end__ = . ;
|
||||
end = . ;
|
||||
_end = . ;
|
||||
__end = . ;
|
||||
} :text
|
||||
.stab :
|
||||
{
|
||||
*(.stab)
|
||||
}
|
||||
.stabstr :
|
||||
{
|
||||
*(.stabstr)
|
||||
} :text
|
||||
/DISCARD/ :
|
||||
{
|
||||
*(.note.gnu.property)
|
||||
*(.comment)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
70
boot/print.c
Normal file
70
boot/print.c
Normal file
@@ -0,0 +1,70 @@
|
||||
#include <u.h>
|
||||
#include "dat.h"
|
||||
#include "fn.h"
|
||||
|
||||
#define TABWIDTH 8
|
||||
#define DEL '\177'
|
||||
|
||||
static void conputc(int c);
|
||||
static int congetc(void);
|
||||
|
||||
static int pos = 0;
|
||||
|
||||
int
|
||||
getchar(void)
|
||||
{
|
||||
int c;
|
||||
|
||||
c = congetc();
|
||||
if( c == '\r')
|
||||
c = '\n';
|
||||
if((c < ' ' && c != '\n') || c == DEL)
|
||||
return c;
|
||||
putchar(c);
|
||||
return c;
|
||||
}
|
||||
|
||||
void
|
||||
putchar(int c)
|
||||
{
|
||||
switch(c){
|
||||
case DEL:
|
||||
conputc('\b');
|
||||
conputc(' ');
|
||||
case '\b':
|
||||
conputc('\b');
|
||||
if(pos)
|
||||
--pos;
|
||||
break;
|
||||
case '\t':
|
||||
do{
|
||||
conputc(' ');
|
||||
}while(++pos % TABWIDTH);
|
||||
break;
|
||||
case '\n':
|
||||
case '\r':
|
||||
conputc(c);
|
||||
pos = 0;
|
||||
break;
|
||||
default:
|
||||
conputc(c);
|
||||
++pos;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
conputc(int c)
|
||||
{
|
||||
if(c){
|
||||
condev.putc(condev.dev, c);
|
||||
if(c == '\n')
|
||||
condev.putc(condev.dev, '\r');
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
congetc(void)
|
||||
{
|
||||
return condev.getc(condev.dev);
|
||||
}
|
||||
13
boot/srt0.S
13
boot/srt0.S
@@ -1,13 +1,12 @@
|
||||
.file "srt0.S"
|
||||
|
||||
#define BOOTSTACK 0xfffc
|
||||
#define CR0_PE 0x00000001 /* Protected mode Enable */
|
||||
#include "def.h"
|
||||
|
||||
.globl end
|
||||
.globl edata
|
||||
.globl Gdtr
|
||||
.globl boot
|
||||
.globl pmm_init
|
||||
.globl pmode_init
|
||||
|
||||
.text
|
||||
.code16
|
||||
@@ -20,14 +19,16 @@ _start:
|
||||
|
||||
1:
|
||||
popl %edx
|
||||
// load GDT
|
||||
cli
|
||||
pushl %cs
|
||||
popl %ds
|
||||
addr32 data32 lgdt (Gdtr - LINKADDR)
|
||||
movl %cr0, %eax
|
||||
// enable protected mode
|
||||
orl $CR0_PE, %eax
|
||||
data32 movl %eax, %cr0
|
||||
data32 ljmp $8, $1f
|
||||
data32 ljmp $S32TEXT, $1f
|
||||
|
||||
1:
|
||||
.code32
|
||||
@@ -37,7 +38,7 @@ _start:
|
||||
mov %ax, %es
|
||||
mov %ax, %fs
|
||||
mov %ax, %gs
|
||||
movl $BOOTSTACK, %esp
|
||||
movl $BOOTSTACKOFF, %esp
|
||||
pushl %edx
|
||||
|
||||
// fill 0 .bss
|
||||
@@ -48,5 +49,5 @@ _start:
|
||||
cld
|
||||
rep; stosb
|
||||
|
||||
call pmm_init
|
||||
call pmode_init
|
||||
call boot
|
||||
|
||||
Reference in New Issue
Block a user