Compare commits
10 Commits
11097add40
...
06160c1ed3
| Author | SHA1 | Date | |
|---|---|---|---|
| 06160c1ed3 | |||
| 14fac398c5 | |||
|
|
bc671ff92b | ||
| 8ad0446359 | |||
| e74cf22714 | |||
|
|
a9a1ad666d | ||
|
|
98601ac381 | ||
| b1f7092fe2 | |||
| c9c820840f | |||
| 8336f11b2a |
@ -1,6 +1,10 @@
|
||||
# FAT16 bootloader
|
||||
x86 FAT16 bootloader
|
||||
|
||||
|
||||
# Feature
|
||||
* [serial console](https://github.com/Hojun-Cho/bootloader/blob/master/boot/sricon.c)
|
||||
* [prompt](https://github.com/Hojun-Cho/bootloader/blob/98601ac381e30d98b4f3f2c20a733beebf9c2ee3/boot/boot.c#L105)
|
||||
|
||||
### How to run
|
||||
1. install image to device
|
||||
install to device
|
||||
@ -32,4 +36,4 @@
|
||||
1. set Global Descriptor Table
|
||||
2. enter protected mode
|
||||
2. set Interrupt Descriptor Table
|
||||
3. call boot function
|
||||
3. call boot function
|
||||
|
||||
@ -5,7 +5,7 @@ PROG = boot
|
||||
SRCS = srt0.S gdt.S boot.c
|
||||
OBJS = srt0.o gdt.o boot.o
|
||||
|
||||
ESRCS = pccon.c sricon.c print.c a20.c time.c
|
||||
ESRCS = pccon.c sricon.c print.c fmt.c a20.c time.c mem.c cpu.c alloc.c disk.c
|
||||
OBJS += $(ESRCS:.c=.o)
|
||||
|
||||
include $(SDIR)/Makefile.inc
|
||||
|
||||
67
boot/alloc.c
Normal file
67
boot/alloc.c
Normal file
@ -0,0 +1,67 @@
|
||||
#include <u.h>
|
||||
#include "dat.h"
|
||||
#include "fn.h"
|
||||
|
||||
// only for booting
|
||||
|
||||
typedef struct FreeList FreeList;
|
||||
static struct FreeList{
|
||||
uint size;
|
||||
FreeList *next;
|
||||
} *freed;
|
||||
|
||||
extern char end[];
|
||||
static char *top = end;
|
||||
|
||||
static void
|
||||
putfreed(FreeList *p)
|
||||
{
|
||||
p->next = nil;
|
||||
if(freed){
|
||||
p->next = freed;
|
||||
freed = p;
|
||||
}else
|
||||
freed = p;
|
||||
}
|
||||
|
||||
static FreeList*
|
||||
getfreed(uint n)
|
||||
{
|
||||
for(FreeList *p=freed,*l=freed; p; p=p->next){
|
||||
if(p->size >= n){
|
||||
l->next = p->next;
|
||||
if(p == freed)
|
||||
freed = nil;
|
||||
return p;
|
||||
}
|
||||
l = p;
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
void*
|
||||
alloc(uint n)
|
||||
{
|
||||
FreeList *p;
|
||||
|
||||
p = getfreed(n);
|
||||
if(p == nil){
|
||||
p = (FreeList*)top;
|
||||
p->size = n;
|
||||
p->next = nil;
|
||||
memset(p+sizeof(*p), 0, n);
|
||||
top += n + sizeof(*p);
|
||||
}
|
||||
if(debug) print("alloc %x %ud\n", &p[1], n);
|
||||
return &p[1];
|
||||
}
|
||||
|
||||
void
|
||||
free(void *src)
|
||||
{
|
||||
FreeList *p;
|
||||
|
||||
p = (FreeList*)((char*)src-sizeof(FreeList));
|
||||
if(debug) print("free %x %ud\n", src, p->size);
|
||||
putfreed(p);
|
||||
}
|
||||
17
boot/boot.c
17
boot/boot.c
@ -6,9 +6,11 @@ static void coninit(void);
|
||||
static void machdep(void);
|
||||
|
||||
void (*probe1[])(void) = {
|
||||
a20up, coninit,
|
||||
a20up, coninit, memprobe,
|
||||
cpuidprobe,
|
||||
};
|
||||
void (*probe2[])(void) = {
|
||||
diskprobe,
|
||||
};
|
||||
|
||||
BootProbe probes[] = {
|
||||
@ -31,7 +33,11 @@ ConDev contab[CON_END] = {
|
||||
.init = cominit,
|
||||
},
|
||||
};
|
||||
|
||||
ConDev *con = &contab[0];
|
||||
BIOSmmap biosmmap[64];
|
||||
uint cnvmem, extmem;
|
||||
int debug = BOOT_DEBUG;
|
||||
|
||||
static void
|
||||
coninit(void)
|
||||
@ -92,9 +98,14 @@ done:
|
||||
void
|
||||
boot(int bootdev)
|
||||
{
|
||||
print("\n\n===> Hello world <===\n\tBooted on disk 0x%x\n", bootdev);
|
||||
machdep();
|
||||
BIOSdisk d = {0,};
|
||||
|
||||
fmtinstall('D', fmtdisk);
|
||||
print("\n===> Hello world <===\n\t"
|
||||
"Booted on disk 0x%x debug:%d\n\t", bootdev, debug);
|
||||
machdep();
|
||||
|
||||
bdiskget(bootdev, &d);
|
||||
for(;;){
|
||||
char buf[8192];
|
||||
|
||||
|
||||
56
boot/cpu.c
Normal file
56
boot/cpu.c
Normal file
@ -0,0 +1,56 @@
|
||||
#include <u.h>
|
||||
#include "dat.h"
|
||||
#include "fn.h"
|
||||
|
||||
#define EFLAG_ID 0x00200000
|
||||
#define CPUID(code, a, b, c, d) \
|
||||
__asm volatile("cpuid" \
|
||||
: "=a" (a), "=b" (b), "=c" (c), "=d" (d) \
|
||||
: "a" (code))
|
||||
|
||||
void*
|
||||
memset(void *dst, int v, int l)
|
||||
{
|
||||
char *p = dst;
|
||||
for(int i = 0; i < l; ++i)
|
||||
*p++ = 0;
|
||||
return dst;
|
||||
}
|
||||
|
||||
void
|
||||
cpuidprobe(void)
|
||||
{
|
||||
int canuse;
|
||||
union{
|
||||
struct{u32 a,b,d,c;};
|
||||
char arr[16];
|
||||
}r = {0,};
|
||||
|
||||
__asm volatile("pushfl\n\t"
|
||||
"popl %2\n\t"
|
||||
"xorl %2, %0\n\t" /* Invert ID sotred in EFLAGS */
|
||||
"pushl %0\n\t"
|
||||
"popfl\n\t"
|
||||
"pushfl\n\t"
|
||||
"popl %0\n\t"
|
||||
"xorl %2, %0\n\t"
|
||||
: "=r" (canuse)
|
||||
: "0" (EFLAG_ID), "r" (0) /* "EFLAGS_ID" same location "canuse" */
|
||||
: "cc");
|
||||
if(canuse != EFLAG_ID){
|
||||
print("cpuid not available\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// print vendor
|
||||
CPUID(0x00, r.a, r.b, r.c, r.d);
|
||||
print("CPU vender: %s\n", r.arr+4);
|
||||
// Is running on Hypervisor?
|
||||
// But nothing to do...
|
||||
memset(&r, 0,sizeof(r));
|
||||
CPUID(0x01, r.a, r.b, r.c, r.d);
|
||||
if(r.c & (1<<31)){
|
||||
CPUID(1<<30, r.a, r.b, r.c, r.d);
|
||||
print("Running on Hypervisor: %s\n", r.arr+4);
|
||||
}
|
||||
}
|
||||
67
boot/dat.h
67
boot/dat.h
@ -2,6 +2,13 @@
|
||||
// 0x60 Read/Write Data Port
|
||||
// 0x64 Read Status Register
|
||||
// 0x64 Write Command Register
|
||||
#define TABWIDTH 8
|
||||
#ifndef BOOT_DEBUG
|
||||
#define BOOT_DEBUG 1
|
||||
#endif
|
||||
|
||||
#define DOSPARTOFF 446
|
||||
#define NDOSPART 4
|
||||
|
||||
enum{
|
||||
CON_PC,
|
||||
@ -36,6 +43,63 @@ struct ConDev{
|
||||
uint dev;
|
||||
uchar pri; // the higher the better
|
||||
};
|
||||
typedef struct{
|
||||
u64 addr; /* Beginning of block */
|
||||
u64 size; /* Size of block */
|
||||
u32 type; /* Type of block */
|
||||
} __attribute__((packed)) BIOSmmap;
|
||||
|
||||
// fmt.c
|
||||
typedef struct{
|
||||
int ucase;
|
||||
int padch;
|
||||
char *p;
|
||||
char *ep;
|
||||
int f1, f2, f3;
|
||||
va_list ap;
|
||||
}Op;
|
||||
|
||||
// disk.c
|
||||
typedef struct{
|
||||
u8 flag; /* bootstrap flags */
|
||||
u8 bhd; /* begin head */
|
||||
u8 bsec; /* begin sector */
|
||||
u8 bcyl; /* begin cylinder */
|
||||
u8 type; /* partition type (see below) */
|
||||
u8 ehd; /* end head */
|
||||
u8 esec; /* end sec2r */
|
||||
u8 ecyl; /* end cylinder */
|
||||
u32 beg; /* absolute starting sectoff number */
|
||||
u32 size; /* partition size in sec2rs */
|
||||
} __attribute__((packed)) DOSpart;
|
||||
|
||||
typedef struct{
|
||||
u8 boot[DOSPARTOFF];
|
||||
DOSpart parts[NDOSPART];
|
||||
u16 sign;
|
||||
} __attribute__((packed)) DOSmbr;
|
||||
|
||||
typedef struct{
|
||||
int n;
|
||||
u32 ncyl;
|
||||
u32 nhead;
|
||||
u32 nsec;
|
||||
i32 edd;
|
||||
u32 dev ;
|
||||
u32 checksum;
|
||||
u32 flag;
|
||||
} __attribute__((packed)) BIOSdisk;
|
||||
|
||||
typedef struct{
|
||||
|
||||
}Disklabel;
|
||||
|
||||
typedef struct{
|
||||
BIOSdisk bdsk; // bios disk info
|
||||
Disklabel label;
|
||||
|
||||
int bootdev, osdev;
|
||||
}Disk;
|
||||
|
||||
// gdt.S
|
||||
extern volatile struct BIOSreg BIOSreg;
|
||||
@ -44,5 +108,8 @@ extern volatile struct BIOSreg BIOSreg;
|
||||
extern void (*probe1[])(void);
|
||||
extern void (*probe2[])(void);
|
||||
extern BootProbe probes[];
|
||||
extern BIOSmmap biosmmap[64];
|
||||
extern ConDev contab[CON_END];
|
||||
extern ConDev *con;
|
||||
extern uint cnvmem, extmem;
|
||||
extern int debug;
|
||||
174
boot/disk.c
Normal file
174
boot/disk.c
Normal file
@ -0,0 +1,174 @@
|
||||
#include <u.h>
|
||||
#include "dat.h"
|
||||
#include "fn.h"
|
||||
|
||||
#define BDA_DISK 0x0475 // of hard disk drives detected
|
||||
#define MAX_DISK_ENTRY 1 // for now
|
||||
|
||||
enum{
|
||||
Bread = 0x4200,
|
||||
Bwrite = 0x4300,
|
||||
};
|
||||
|
||||
// interrupt 41h exension support bitmap
|
||||
enum{
|
||||
Eeda = 0x01, // Extended disk access funcions 42-44,47,48
|
||||
Erdc = 0x02, // removable drive controller functions 45,46,48,49
|
||||
Eedd = 0x04, // Enhanced disk drive functions
|
||||
};
|
||||
|
||||
typedef struct{
|
||||
u8 len;
|
||||
u8 res1;
|
||||
u8 nblk;
|
||||
u8 res2;
|
||||
u16 off;
|
||||
u16 seg;
|
||||
u64 daddr; // starting block
|
||||
}EDDcb;
|
||||
|
||||
Disk disks[MAX_DISK_ENTRY];
|
||||
|
||||
static int
|
||||
ireset(int dev)
|
||||
{
|
||||
int rv;
|
||||
|
||||
__asm volatile("int $0x33\n\t"
|
||||
"setc %b0"
|
||||
: "=a" (rv)
|
||||
: "0" (0), "d" (dev)
|
||||
: "%ecx", "%cc");
|
||||
return (rv&0xff) ? -1 : 0;
|
||||
}
|
||||
|
||||
// Bit(s) Description (Table 00271)
|
||||
// 0 extended disk access functions (AH=42h-44h,47h,48h) supported
|
||||
// 1 removable drive controller functions (AH=45h,46h,48h,49h,INT 15/AH=52h) supported
|
||||
// 2 enhanced disk drive (EDD) functions (AH=48h,AH=4Eh) supported.
|
||||
// Extended drive parameter table is valid (see #00273,#00278)
|
||||
// 3-15 reserved (0)
|
||||
static __inline int
|
||||
ieddsuport(BIOSdisk *d)
|
||||
{
|
||||
int bmap, rv;
|
||||
|
||||
__asm volatile("int $0x33\n\t"
|
||||
"setc %b0"
|
||||
: "=a" (rv), "=c" (bmap)
|
||||
: "0" (0x4100), "b" (0x55aa), "d" (d->n)
|
||||
: "cc");
|
||||
if(rv&0xff || (BIOSreg.bx&0xffff) != 0xaa55)
|
||||
return -1;
|
||||
d->edd = (bmap&0xffff) | ((rv&0xff)<<16);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static __inline int
|
||||
bdiskinfo(BIOSdisk *d)
|
||||
{
|
||||
int rv;
|
||||
|
||||
// CL = maximum sector number (bits 5-0)
|
||||
// high two bits of maximum cylinder number (bits 7-6)
|
||||
__asm volatile("int $0x33\n\t"
|
||||
"setc %b0\n\t"
|
||||
"movzbl %h1, %1\n\t"
|
||||
"movzbl %%cl, %3; andb $0x3f, %b3\n\t"
|
||||
"xchgb %%cl, %%ch; rolb $2, %%ch"
|
||||
: "=a" (rv), "=d" (d->nhead), "=c" (d->ncyl), "=b" (d->nsec)
|
||||
: "0" (0x0800), "1" (d->n)
|
||||
: "cc");
|
||||
return (rv&0xff) == 0 ? 0 : -1;
|
||||
}
|
||||
|
||||
int
|
||||
bdiskget(int dev, BIOSdisk *d)
|
||||
{
|
||||
if(ireset(dev)){
|
||||
print("Can't reset disk\n");
|
||||
return -1;
|
||||
}
|
||||
d->n = dev;
|
||||
if(bdiskinfo(d)){
|
||||
print("Can't read disk\n");
|
||||
return -1;
|
||||
}
|
||||
if(ieddsuport(d)){
|
||||
print("edd not supported\n");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
diskrw(uint rw, int dev, u32 daddr, u32 blk, void *buf)
|
||||
{
|
||||
int rv;
|
||||
volatile EDDcb cb = {0,};
|
||||
|
||||
cb.len = sizeof(cb);
|
||||
cb.nblk = blk;
|
||||
cb.seg = ((u32)buf>>4 & 0xffff);
|
||||
cb.off = (u32)buf & 0xf;
|
||||
cb.daddr = daddr;
|
||||
if(cb.seg==0 || cb.off==0)
|
||||
return -1;
|
||||
BIOSreg.ds = (u32)&cb >> 4;
|
||||
__asm volatile ("int $0x33\n\t"
|
||||
"setc %b0\n\t"
|
||||
: "=a" (rv)
|
||||
: "0" (rw), "d" (dev), "S" ((int)(&cb)&0xf)
|
||||
: "%ecx", "cc");
|
||||
return rv&0xff? -1 : 0;
|
||||
}
|
||||
|
||||
static int
|
||||
findos(BIOSdisk *bd)
|
||||
{
|
||||
DOSmbr mbr = {0,};
|
||||
|
||||
if(diskrw(Bread, bd->n, 0, 1, &mbr)){
|
||||
print("Can't find os disk %d\n", bd->n);
|
||||
return -1;
|
||||
}
|
||||
print("found os disk signature: 0x%x\n", mbr.sign);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
findlabel(BIOSdisk *b, Disklabel *dl)
|
||||
{
|
||||
if(b->n & 0x80){
|
||||
findos(b);
|
||||
return 0; // for now
|
||||
}
|
||||
print("Can't found disk label:%x \n", b->n);
|
||||
return -1;
|
||||
}
|
||||
|
||||
void
|
||||
diskprobe(void)
|
||||
{
|
||||
int n = MIN((int)*(char*)BDA_DISK, MAX_DISK_ENTRY);
|
||||
|
||||
for(int i = 0x80; i < 0x80+n; ++i){
|
||||
if(bdiskget(i, &disks[i].bdsk))
|
||||
return;
|
||||
print("Disnk info: %D\n", disks[i].bdsk);
|
||||
if(findlabel(&disks[i].bdsk, &disks[i].label)){
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
fmtdisk(Op *op)
|
||||
{
|
||||
dofmt(op, "disk:%x cyl:%d head:%d sec:%d edd:%d");
|
||||
// for skip va_list
|
||||
USED(va_arg(op->ap, u32));
|
||||
USED(va_arg(op->ap, u32));
|
||||
USED(va_arg(op->ap, u32));
|
||||
return 0;
|
||||
}
|
||||
304
boot/fmt.c
Normal file
304
boot/fmt.c
Normal file
@ -0,0 +1,304 @@
|
||||
#include <u.h>
|
||||
#include "dat.h"
|
||||
#include "fn.h"
|
||||
|
||||
#define MAXCON 30
|
||||
#define IDIGIT 30
|
||||
|
||||
enum{
|
||||
FLONG = (1<<0),
|
||||
FSHORT = (1<<2),
|
||||
FUNSIGN = (1<<3),
|
||||
};
|
||||
|
||||
static void put(Op*, int);
|
||||
static int noconv(Op*);
|
||||
static int cconv(Op*);
|
||||
static int dconv(Op*);
|
||||
static int hconv(Op*);
|
||||
static int lconv(Op*);
|
||||
static int sconv(Op*);
|
||||
static int uconv(Op*);
|
||||
static int xconv(Op*);
|
||||
static int Xconv(Op*);
|
||||
static int percent(Op*);
|
||||
|
||||
static int (*fmtconv[MAXCON])(Op*) = {
|
||||
noconv,
|
||||
cconv, dconv, hconv, lconv,
|
||||
sconv, uconv, xconv, Xconv,
|
||||
percent,
|
||||
};
|
||||
|
||||
int fmtindex[128] = {
|
||||
['c'] = 1,
|
||||
['d'] = 2,
|
||||
['h'] = 3,
|
||||
['l'] = 4,
|
||||
['s'] = 5,
|
||||
['u'] = 6,
|
||||
['x'] = 7,
|
||||
['X'] = 8,
|
||||
['%'] = 9,
|
||||
};
|
||||
int convcnt = 11;
|
||||
|
||||
int
|
||||
strlen(char *s)
|
||||
{
|
||||
char *p = s;
|
||||
|
||||
while(*p)
|
||||
++p;
|
||||
return p-s;
|
||||
}
|
||||
|
||||
int
|
||||
fmtinstall(int c, int (*f)(Op*))
|
||||
{
|
||||
c &= 0177;
|
||||
if(fmtindex[c] == 0){
|
||||
if(convcnt + 1 >= MAXCON)
|
||||
return -1;
|
||||
fmtindex[c] = convcnt++;
|
||||
}
|
||||
fmtconv[fmtindex[c]] = f;
|
||||
return 0;
|
||||
}
|
||||
|
||||
char*
|
||||
dofmt(Op *op, char *fmt)
|
||||
{
|
||||
int sf1, c;
|
||||
|
||||
while(1){
|
||||
c = *fmt++;
|
||||
if(c != '%'){
|
||||
if(c == 0){
|
||||
if(op->p < op->ep)
|
||||
*op->p = 0;
|
||||
return op->p;
|
||||
}
|
||||
put(op, c);
|
||||
continue;
|
||||
}
|
||||
op->f2 = -1;
|
||||
op->f1 = op->f3 = 0;
|
||||
op->padch = sf1 = 0;
|
||||
c = *fmt++;
|
||||
if(c == '-'){
|
||||
sf1 = 1;
|
||||
c = *fmt++;
|
||||
}else if(c == '0' || c == ' '){
|
||||
op->padch = c;
|
||||
c = *fmt++;
|
||||
}
|
||||
while(c >= '0' && c <= '9'){
|
||||
op->f1 = op->f1*10 + c-'0';
|
||||
c = *fmt++;
|
||||
}
|
||||
if(sf1)
|
||||
op->f1 = -op->f1;
|
||||
if(c != '.')
|
||||
goto conv;
|
||||
c = *fmt++;
|
||||
while(c >= '0' && c <= '9'){
|
||||
if(op->f2 < 0)
|
||||
op->f2 = 0;
|
||||
op->f2 = op->f2*10 + c-'0';
|
||||
c = *fmt++;
|
||||
}
|
||||
conv:
|
||||
if(c == 0)
|
||||
fmt -= 1;
|
||||
c = (*fmtconv[fmtindex[c&0177]])(op);
|
||||
if(c < 0){
|
||||
op->f3 |= -c;
|
||||
c = *fmt++;
|
||||
goto conv;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
strconv(char *s, Op *op, int f1, int f2)
|
||||
{
|
||||
int n, c;
|
||||
char *p;
|
||||
|
||||
n = strlen(s);
|
||||
if(f1 >= 0)
|
||||
while(n < f1){
|
||||
put(op, op->padch);
|
||||
n += 1;
|
||||
}
|
||||
for(p=s; (c = *p++);)
|
||||
if(f2){
|
||||
put(op, c);
|
||||
f2 -= 1;
|
||||
}
|
||||
if(f1 < 0){
|
||||
f1 = -f1;
|
||||
while(n < f1){
|
||||
put(op, ' ');
|
||||
n += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
numconv(Op *op, int base)
|
||||
{
|
||||
char b[IDIGIT];
|
||||
int i,f,n;
|
||||
long v;
|
||||
short h;
|
||||
|
||||
i = IDIGIT-1;
|
||||
f = 0;
|
||||
b[i] = 0;
|
||||
switch(op->f3 & (FLONG|FSHORT|FUNSIGN)){
|
||||
case FLONG:
|
||||
v = va_arg(op->ap, long);
|
||||
break;
|
||||
case FUNSIGN|FLONG:
|
||||
v = va_arg(op->ap, ulong);
|
||||
break;
|
||||
case FSHORT:
|
||||
v = h = va_arg(op->ap, short);
|
||||
break;
|
||||
case FUNSIGN|FSHORT:
|
||||
h = va_arg(op->ap, ushort);
|
||||
v = (ushort)h;
|
||||
break;
|
||||
case FUNSIGN:
|
||||
v = va_arg(op->ap, unsigned);
|
||||
break;
|
||||
default:
|
||||
v = va_arg(op->ap, int);
|
||||
break;
|
||||
}
|
||||
if((op->f3 & FUNSIGN) && v < 0){
|
||||
v = -v;
|
||||
f = 1;
|
||||
}
|
||||
while(--i){
|
||||
n = v % base;
|
||||
n += '0';
|
||||
if(n > '9'){
|
||||
n += 'a' - ('9'+1);
|
||||
if(op->ucase)
|
||||
n += 'A'-'a';
|
||||
}
|
||||
b[i] = n;
|
||||
v = (ulong)v / base;
|
||||
if(i < 2)
|
||||
break;
|
||||
if(op->f2 >= 0 && i >= IDIGIT - op->f2)
|
||||
continue;
|
||||
if(v <= 0)
|
||||
break;
|
||||
}
|
||||
if(f)
|
||||
b[--i] = '-';
|
||||
strconv(b+i, op, op->f1, -1);
|
||||
}
|
||||
|
||||
static int
|
||||
noconv(Op *op)
|
||||
{
|
||||
strconv("***ERROR: noconv***", op, 0, -1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
cconv(Op *op)
|
||||
{
|
||||
char b[2];
|
||||
|
||||
b[0] = va_arg(op->ap, char);
|
||||
b[1] = 0;
|
||||
strconv(b, op, op->f1, -1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
dconv(Op *op)
|
||||
{
|
||||
numconv(op, 10);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
hconv(Op *op)
|
||||
{
|
||||
return -FSHORT;
|
||||
}
|
||||
|
||||
static int
|
||||
lconv(Op *op)
|
||||
{
|
||||
return -FLONG;
|
||||
}
|
||||
|
||||
static int
|
||||
uconv(Op *op)
|
||||
{
|
||||
return -FUNSIGN;
|
||||
}
|
||||
|
||||
static int
|
||||
sconv(Op *op)
|
||||
{
|
||||
char *p;
|
||||
|
||||
p = va_arg(op->ap, char*);
|
||||
strconv(p?p:"<nil>", op, op->f1, op->f2);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
xconv(Op *op)
|
||||
{
|
||||
numconv(op, 16);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
Xconv(Op *op)
|
||||
{
|
||||
op->ucase = 1;
|
||||
numconv(op, 16);
|
||||
op->ucase = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
percent(Op *op)
|
||||
{
|
||||
put(op, '%');
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
put(Op *op, int c)
|
||||
{
|
||||
static int pos;
|
||||
int opos;
|
||||
|
||||
if(c == 0)
|
||||
return;
|
||||
if(c == '\t'){
|
||||
opos = pos;
|
||||
pos = (opos+TABWIDTH) & (~(TABWIDTH-1));
|
||||
while(opos++ < pos && op->p < op->ep)
|
||||
*op->p++ = ' ';
|
||||
return;
|
||||
}
|
||||
if(op->p < op->ep){
|
||||
*op->p++ = c;
|
||||
pos++;
|
||||
}
|
||||
if(c == '\n')
|
||||
pos = 0;
|
||||
}
|
||||
34
boot/fn.h
34
boot/fn.h
@ -1,3 +1,6 @@
|
||||
#define MAX(x, y) ((x)>(y)?(x):(y))
|
||||
#define MIN(x, y) ((x)<(y)?(x):(y))
|
||||
|
||||
// console.c
|
||||
void cominit(ConDev *d);
|
||||
void pcinit(ConDev *d);
|
||||
@ -8,17 +11,44 @@ int comprobe(ConDev *d);
|
||||
int comgetc(int dev);
|
||||
void computc(int dev, int c);
|
||||
|
||||
// fmt.c
|
||||
char* dofmt(Op *op, char *fmt);
|
||||
int fmtinstall(int c, int (*f)(Op*));
|
||||
char *doprint(char *p, char *ep, char *fmt, va_list ap);
|
||||
int strlen(char *s);
|
||||
|
||||
// print.c
|
||||
void putchar(int c);
|
||||
void putstr(char *s, int l);
|
||||
int getchar(void);
|
||||
void print(const char *fmt, ...);
|
||||
char* doprint(char *p, char *ep, char *fmt, va_list);
|
||||
int print(char *fmt, ...);
|
||||
int snprint(char *buf, int len, char *fmt, ...);
|
||||
|
||||
// a20.c
|
||||
void a20up(void);
|
||||
|
||||
// long.c
|
||||
// mem.c
|
||||
void memprobe(void);
|
||||
|
||||
// cpu.c
|
||||
void cpuidprobe(void);
|
||||
|
||||
// time.c
|
||||
long getsecs(void);
|
||||
|
||||
// alloc.c
|
||||
void *alloc(uint);
|
||||
void free(void*);
|
||||
|
||||
// disk.c
|
||||
int bdiskget(int dev, BIOSdisk *d);
|
||||
int fmtdisk(Op *op);
|
||||
void diskprobe(void);
|
||||
|
||||
// util
|
||||
void* memset(void *dst, int v, int l);
|
||||
|
||||
static __inline int
|
||||
major(int x)
|
||||
{
|
||||
|
||||
51
boot/gdt.S
51
boot/gdt.S
@ -2,6 +2,16 @@
|
||||
|
||||
#include "def.h"
|
||||
|
||||
#define AX 0
|
||||
#define CX 4
|
||||
#define DX 8
|
||||
#define BX 12
|
||||
#define BP 16
|
||||
#define SI 20
|
||||
#define DI 24
|
||||
#define DS 28
|
||||
#define ES 32
|
||||
|
||||
#define GEN_LABEL(n) X##n
|
||||
|
||||
// idt entry
|
||||
@ -63,22 +73,12 @@
|
||||
\
|
||||
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 pmode_init
|
||||
.globl BIOSreg
|
||||
BIOSreg:
|
||||
.space 36, 0
|
||||
|
||||
// Table
|
||||
// IDTR offset + 0 : entry 0
|
||||
@ -246,11 +246,9 @@ EMUh: // build stack for real mode
|
||||
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
|
||||
movl BIOSreg+ES, %eax
|
||||
mov %eax, 7f
|
||||
movl BIOS_DS, %eax
|
||||
movl $0x00, %eax
|
||||
movl BIOSreg+DS, %eax
|
||||
mov %eax, 6f
|
||||
|
||||
prot2real
|
||||
@ -300,12 +298,13 @@ intno = . -1;
|
||||
// movl $Leax, %eax
|
||||
.byte 0xb8
|
||||
4: .long 0x90909090
|
||||
mov %eax, BIOS_BX
|
||||
movl %eax, BIOSreg+BX
|
||||
|
||||
// movl $Leax, %eax
|
||||
.byte 0xb8
|
||||
3: .long 0x90909090
|
||||
mov %eax, BIOS_ES
|
||||
movl %eax, BIOSreg+ES
|
||||
|
||||
|
||||
// movl $Leax, %eax
|
||||
.byte 0xb8
|
||||
@ -318,13 +317,13 @@ intno = . -1;
|
||||
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
|
||||
movl %eax, BIOSreg+AX
|
||||
movl %ecx, BIOSreg+CX
|
||||
movl %edx, BIOSreg+DX
|
||||
movl %ebp, BIOSreg+BP
|
||||
movl %esi, BIOSreg+SI
|
||||
movl %edi, BIOSreg+DI
|
||||
|
||||
|
||||
// clear NT(Nested Task Flag: 14) flag in eflag
|
||||
// if 1 : interrupting
|
||||
|
||||
81
boot/mem.c
Normal file
81
boot/mem.c
Normal file
@ -0,0 +1,81 @@
|
||||
#include <u.h>
|
||||
#include "dat.h"
|
||||
#include "fn.h"
|
||||
|
||||
#define IOMEM_BEGIN 0x0A0000
|
||||
#define IOMEM_END 0x100000
|
||||
|
||||
enum{
|
||||
MAP_END = 0x00,
|
||||
MAP_FREE = 0x01,
|
||||
MAP_RES = 0x02,
|
||||
MAP_ACPI_RECLAM = 0x03,
|
||||
MAP_ACPI_NVS = 0x04,
|
||||
};
|
||||
|
||||
static BIOSmmap*
|
||||
int15_E820(BIOSmmap *m)
|
||||
{
|
||||
int rc, sig, off = 0;
|
||||
do{
|
||||
BIOSreg.es = ((uint)(m) >> 4);
|
||||
__asm volatile("int $0x35; setc %b1"
|
||||
: "=a" (sig), "=d" (rc), "=b" (off)
|
||||
: "0" (0xE820), "1" (0x534d4150), "b" (off),
|
||||
"c" (sizeof(*m)), "D" (((uint)m) & 0xf)
|
||||
: "cc", "memory");
|
||||
|
||||
off = BIOSreg.bx;
|
||||
if(rc &0xff || sig !=0x534d4150){
|
||||
break;
|
||||
if(m->type == 0)
|
||||
m->type = MAP_RES;
|
||||
}
|
||||
m++;
|
||||
}while(off);
|
||||
return m;
|
||||
}
|
||||
|
||||
static void
|
||||
dumpmem(BIOSmmap *m)
|
||||
{
|
||||
ulong tot = 0;
|
||||
|
||||
for(BIOSmmap *p=m; p->type != MAP_END; ++p){
|
||||
print("MEM % 2ud type %ud size % 10udKB at %08x:%08x\n",
|
||||
p-m, p->type, (uint)(p->size/1024), (uint)(p->addr>>32), (uint)p->addr);
|
||||
if(p->type == MAP_FREE)
|
||||
tot += p->size/1024;
|
||||
}
|
||||
print("RAM low:%udKB high:%udKB\n", cnvmem, extmem);
|
||||
print("Total free memory: %udKB\n", tot);
|
||||
}
|
||||
|
||||
static int
|
||||
isa20done(void)
|
||||
{
|
||||
register char *a = (char *)0x100000;
|
||||
register char *b = (char *)0x000000;
|
||||
|
||||
return *a != *b;
|
||||
}
|
||||
|
||||
void
|
||||
memprobe(void)
|
||||
{
|
||||
BIOSmmap *m;
|
||||
|
||||
cnvmem = extmem = 0;
|
||||
m = int15_E820(biosmmap);
|
||||
m->type = MAP_END;
|
||||
for(m = biosmmap; m->type != MAP_END; ++m){
|
||||
if(m->type != MAP_FREE || m->size <= 0)
|
||||
continue;
|
||||
if(m->addr < IOMEM_BEGIN)
|
||||
cnvmem = MAX(cnvmem, m->addr + m->size)/1024;
|
||||
if(m->addr >= IOMEM_END)
|
||||
extmem += m->size/1024;
|
||||
}
|
||||
dumpmem(biosmmap);
|
||||
print("A20:%s\n", isa20done() ? "ok" : "no");
|
||||
}
|
||||
93
boot/print.c
93
boot/print.c
@ -2,61 +2,49 @@
|
||||
#include "dat.h"
|
||||
#include "fn.h"
|
||||
|
||||
#define TABWIDTH 4
|
||||
#define BUFSIZE 1024
|
||||
|
||||
static void conputc(int c);
|
||||
static void conputc(int);
|
||||
static int congetc(void);
|
||||
static void doprint(void (*put)(int), const char *fmt, va_list ap);
|
||||
static void putint(void (*put)(int), int n, const char *sym, int base);
|
||||
static int pos = 0;
|
||||
|
||||
void
|
||||
print(const char *fmt, ...)
|
||||
char*
|
||||
doprint(char *p, char *ep, char *fmt, va_list ap)
|
||||
{
|
||||
Op op = { .p = p, .ep = ep, .ap = ap };
|
||||
return dofmt(&op, fmt);
|
||||
}
|
||||
|
||||
int
|
||||
print(char *fmt, ...)
|
||||
{
|
||||
char buf[BUFSIZE], *p;
|
||||
va_list args;
|
||||
|
||||
va_start(args, fmt);
|
||||
doprint(putchar, fmt, args);
|
||||
p = doprint(buf, buf+sizeof(buf), fmt, args);
|
||||
va_end(args);
|
||||
putstr(buf, p-buf);
|
||||
return p-buf;
|
||||
}
|
||||
|
||||
static void
|
||||
doprint(void (*put)(int), const char *s, va_list ap)
|
||||
int
|
||||
snprint(char *buf, int len, char *fmt, ...)
|
||||
{
|
||||
while(*s){
|
||||
if(*s != '%'){
|
||||
put(*s++);
|
||||
continue;
|
||||
}
|
||||
++s;
|
||||
switch(*s){
|
||||
case 'd':
|
||||
putint(put, va_arg(ap,int), "0123456789", 10);
|
||||
break;
|
||||
case 'x':
|
||||
putint(put, va_arg(ap,int), "0123456789abcdef", 16);
|
||||
break;
|
||||
case 'X':
|
||||
putint(put, va_arg(ap,int), "0123456789ABCDEF", 16);
|
||||
break;
|
||||
case 's':
|
||||
for(char *p=va_arg(ap,char*); *p; ++p)
|
||||
put(*p);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
++s;
|
||||
}
|
||||
}
|
||||
char *p;
|
||||
va_list args;
|
||||
|
||||
va_start(args, fmt);
|
||||
p = doprint(buf, buf+len, fmt, args);
|
||||
va_end(args);
|
||||
return p-buf;
|
||||
}
|
||||
|
||||
int
|
||||
getchar(void)
|
||||
{
|
||||
int c;
|
||||
|
||||
c = congetc();
|
||||
c = congetc();
|
||||
if(c == '\r')
|
||||
c = '\n';
|
||||
if((c < ' ' && c != '\n') || c == '\177')
|
||||
@ -65,6 +53,13 @@ getchar(void)
|
||||
return c;
|
||||
}
|
||||
|
||||
void
|
||||
putstr(char *s, int l)
|
||||
{
|
||||
while(l--)
|
||||
putchar(*s++);
|
||||
}
|
||||
|
||||
void
|
||||
putchar(int c)
|
||||
{
|
||||
@ -72,24 +67,20 @@ putchar(int c)
|
||||
case '\177':
|
||||
conputc('\b');
|
||||
conputc(' ');
|
||||
break;
|
||||
case '\b':
|
||||
conputc('\b');
|
||||
if(pos > 0)
|
||||
--pos;
|
||||
break;
|
||||
case '\t':
|
||||
do{
|
||||
for(int i = 0; i < TABWIDTH; ++i)
|
||||
conputc(' ');
|
||||
}while(++pos % TABWIDTH);
|
||||
break;
|
||||
case '\n':
|
||||
case '\r':
|
||||
conputc(c);
|
||||
pos = 0;
|
||||
break;
|
||||
default:
|
||||
conputc(c);
|
||||
++pos;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -109,19 +100,3 @@ congetc(void)
|
||||
{
|
||||
return con->getc(con->dev);
|
||||
}
|
||||
|
||||
static void
|
||||
putint(void (*put)(int), int n, const char *sym, int base)
|
||||
{
|
||||
int i;
|
||||
char buf[16];
|
||||
|
||||
i = 0;
|
||||
do{
|
||||
buf[i++] = n%base;
|
||||
n /= base;
|
||||
}while(n);
|
||||
do{
|
||||
put((int)sym[(int)buf[--i]]);
|
||||
}while(i);
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user