Compare commits

...

10 Commits

Author SHA1 Message Date
06160c1ed3 add disk read
not implementing disk write yet
2024-12-16 23:23:18 +09:00
14fac398c5 add disk info interrupt 2024-12-12 17:25:00 +09:00
O_WRONLY
bc671ff92b
Merge pull request #1 from Hojun-Cho/fix-fmt
fix fmt,print
2024-12-12 17:24:26 +09:00
8ad0446359 fix fmt,print
for easy to use fmtinstall
2024-12-12 17:22:49 +09:00
e74cf22714 add heap alloc function
Physically contiguous memory
2024-12-12 14:08:01 +09:00
O_WRONLY
a9a1ad666d
Update README.md 2024-12-10 23:50:23 +09:00
Hojun-Cho
98601ac381 add CPUID probe
Just print vendor, Hypervisor...
2024-12-09 21:28:45 +09:00
b1f7092fe2 add fmt.c for print function
don't process 64-bit format such as '%llu' in print function.
2024-12-09 15:43:58 +09:00
c9c820840f add memprobe
NOTE: print "%llx" "%lld" not working now
2024-12-08 23:14:32 +09:00
8336f11b2a fix protection fault from GDT 2024-12-07 01:14:26 +09:00
12 changed files with 861 additions and 93 deletions

View File

@ -1,6 +1,10 @@
# FAT16 bootloader # FAT16 bootloader
x86 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 ### How to run
1. install image to device 1. install image to device
install to device install to device
@ -32,4 +36,4 @@
1. set Global Descriptor Table 1. set Global Descriptor Table
2. enter protected mode 2. enter protected mode
2. set Interrupt Descriptor Table 2. set Interrupt Descriptor Table
3. call boot function 3. call boot function

View File

@ -5,7 +5,7 @@ PROG = boot
SRCS = srt0.S gdt.S boot.c SRCS = srt0.S gdt.S boot.c
OBJS = srt0.o gdt.o boot.o 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) OBJS += $(ESRCS:.c=.o)
include $(SDIR)/Makefile.inc include $(SDIR)/Makefile.inc

67
boot/alloc.c Normal file
View 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);
}

View File

@ -6,9 +6,11 @@ static void coninit(void);
static void machdep(void); static void machdep(void);
void (*probe1[])(void) = { void (*probe1[])(void) = {
a20up, coninit, a20up, coninit, memprobe,
cpuidprobe,
}; };
void (*probe2[])(void) = { void (*probe2[])(void) = {
diskprobe,
}; };
BootProbe probes[] = { BootProbe probes[] = {
@ -31,7 +33,11 @@ ConDev contab[CON_END] = {
.init = cominit, .init = cominit,
}, },
}; };
ConDev *con = &contab[0]; ConDev *con = &contab[0];
BIOSmmap biosmmap[64];
uint cnvmem, extmem;
int debug = BOOT_DEBUG;
static void static void
coninit(void) coninit(void)
@ -92,9 +98,14 @@ done:
void void
boot(int bootdev) boot(int bootdev)
{ {
print("\n\n===> Hello world <===\n\tBooted on disk 0x%x\n", bootdev); BIOSdisk d = {0,};
machdep();
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(;;){ for(;;){
char buf[8192]; char buf[8192];

56
boot/cpu.c Normal file
View 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);
}
}

View File

@ -2,6 +2,13 @@
// 0x60 Read/Write Data Port // 0x60 Read/Write Data Port
// 0x64 Read Status Register // 0x64 Read Status Register
// 0x64 Write Command Register // 0x64 Write Command Register
#define TABWIDTH 8
#ifndef BOOT_DEBUG
#define BOOT_DEBUG 1
#endif
#define DOSPARTOFF 446
#define NDOSPART 4
enum{ enum{
CON_PC, CON_PC,
@ -36,6 +43,63 @@ struct ConDev{
uint dev; uint dev;
uchar pri; // the higher the better 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 // gdt.S
extern volatile struct BIOSreg BIOSreg; extern volatile struct BIOSreg BIOSreg;
@ -44,5 +108,8 @@ extern volatile struct BIOSreg BIOSreg;
extern void (*probe1[])(void); extern void (*probe1[])(void);
extern void (*probe2[])(void); extern void (*probe2[])(void);
extern BootProbe probes[]; extern BootProbe probes[];
extern BIOSmmap biosmmap[64];
extern ConDev contab[CON_END]; extern ConDev contab[CON_END];
extern ConDev *con; extern ConDev *con;
extern uint cnvmem, extmem;
extern int debug;

174
boot/disk.c Normal file
View 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
View 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;
}

View File

@ -1,3 +1,6 @@
#define MAX(x, y) ((x)>(y)?(x):(y))
#define MIN(x, y) ((x)<(y)?(x):(y))
// console.c // console.c
void cominit(ConDev *d); void cominit(ConDev *d);
void pcinit(ConDev *d); void pcinit(ConDev *d);
@ -8,17 +11,44 @@ int comprobe(ConDev *d);
int comgetc(int dev); int comgetc(int dev);
void computc(int dev, int c); 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 // print.c
void putchar(int c); void putchar(int c);
void putstr(char *s, int l);
int getchar(void); 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 // a20.c
void a20up(void); void a20up(void);
// long.c // mem.c
void memprobe(void);
// cpu.c
void cpuidprobe(void);
// time.c
long getsecs(void); 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 static __inline int
major(int x) major(int x)
{ {

View File

@ -2,6 +2,16 @@
#include "def.h" #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 #define GEN_LABEL(n) X##n
// idt entry // idt entry
@ -63,22 +73,12 @@
\ \
lidt Idtr; 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 .text
.code32 .code32
.globl pmode_init .globl pmode_init
.globl BIOSreg
BIOSreg:
.space 36, 0
// Table // Table
// IDTR offset + 0 : entry 0 // IDTR offset + 0 : entry 0
@ -246,11 +246,9 @@ EMUh: // build stack for real mode
movb %al, intno // save BIOS int vector 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 // BIOS_regs is area for saving the contents of registers returned by the BIOS during a BIOS CALL
movl BIOS_ES, %eax movl BIOSreg+ES, %eax
movl $0x00, %eax
mov %eax, 7f mov %eax, 7f
movl BIOS_DS, %eax movl BIOSreg+DS, %eax
movl $0x00, %eax
mov %eax, 6f mov %eax, 6f
prot2real prot2real
@ -300,12 +298,13 @@ intno = . -1;
// movl $Leax, %eax // movl $Leax, %eax
.byte 0xb8 .byte 0xb8
4: .long 0x90909090 4: .long 0x90909090
mov %eax, BIOS_BX movl %eax, BIOSreg+BX
// movl $Leax, %eax // movl $Leax, %eax
.byte 0xb8 .byte 0xb8
3: .long 0x90909090 3: .long 0x90909090
mov %eax, BIOS_ES movl %eax, BIOSreg+ES
// movl $Leax, %eax // movl $Leax, %eax
.byte 0xb8 .byte 0xb8
@ -318,13 +317,13 @@ intno = . -1;
movb %bh, 0xe*4(%esp) // restore eflags movb %bh, 0xe*4(%esp) // restore eflags
// save register into BIOSREG // save register into BIOSREG
.code32 movl %eax, BIOSreg+AX
movl %eax, BIOS_AX movl %ecx, BIOSreg+CX
movl %ecx, BIOS_CX movl %edx, BIOSreg+DX
movl %edx, BIOS_DX movl %ebp, BIOSreg+BP
movl %ebp, BIOS_BP movl %esi, BIOSreg+SI
movl %esi, BIOS_SI movl %edi, BIOSreg+DI
movl %edi, BIOS_DI
// clear NT(Nested Task Flag: 14) flag in eflag // clear NT(Nested Task Flag: 14) flag in eflag
// if 1 : interrupting // if 1 : interrupting

81
boot/mem.c Normal file
View 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");
}

View File

@ -2,61 +2,49 @@
#include "dat.h" #include "dat.h"
#include "fn.h" #include "fn.h"
#define TABWIDTH 4 #define BUFSIZE 1024
static void conputc(int c); static void conputc(int);
static int congetc(void); 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 char*
print(const char *fmt, ...) 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_list args;
va_start(args, fmt); va_start(args, fmt);
doprint(putchar, fmt, args); p = doprint(buf, buf+sizeof(buf), fmt, args);
va_end(args); va_end(args);
putstr(buf, p-buf);
return p-buf;
} }
static void int
doprint(void (*put)(int), const char *s, va_list ap) snprint(char *buf, int len, char *fmt, ...)
{ {
while(*s){ char *p;
if(*s != '%'){ va_list args;
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;
}
}
va_start(args, fmt);
p = doprint(buf, buf+len, fmt, args);
va_end(args);
return p-buf;
}
int int
getchar(void) getchar(void)
{ {
int c; int c;
c = congetc(); c = congetc();
if(c == '\r') if(c == '\r')
c = '\n'; c = '\n';
if((c < ' ' && c != '\n') || c == '\177') if((c < ' ' && c != '\n') || c == '\177')
@ -65,6 +53,13 @@ getchar(void)
return c; return c;
} }
void
putstr(char *s, int l)
{
while(l--)
putchar(*s++);
}
void void
putchar(int c) putchar(int c)
{ {
@ -72,24 +67,20 @@ putchar(int c)
case '\177': case '\177':
conputc('\b'); conputc('\b');
conputc(' '); conputc(' ');
break;
case '\b': case '\b':
conputc('\b'); conputc('\b');
if(pos > 0)
--pos;
break; break;
case '\t': case '\t':
do{ for(int i = 0; i < TABWIDTH; ++i)
conputc(' '); conputc(' ');
}while(++pos % TABWIDTH);
break; break;
case '\n': case '\n':
case '\r': case '\r':
conputc(c); conputc(c);
pos = 0;
break; break;
default: default:
conputc(c); conputc(c);
++pos;
break; break;
} }
} }
@ -109,19 +100,3 @@ congetc(void)
{ {
return con->getc(con->dev); 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);
}