URL
https://opencores.org/ocsvn/eco32/eco32/trunk
Subversion Repositories eco32
Compare Revisions
- This comparison shows the changes necessary to convert path
/eco32/tags/eco32-0.26/stdalone/wrtmbr
- from Rev 259 to Rev 270
- ↔ Reverse comparison
Rev 259 → Rev 270
/mbr/Makefile
0,0 → 1,24
# |
# Makefile for assembling the default master boot record |
# |
|
BUILD = ../../../build |
|
.PHONY: all clean |
|
all: mbr.dump |
|
mbr.dump: dump mbr.bin |
./dump mbr.bin mbr.dump |
|
dump: dump.c |
gcc -g -Wall -o dump dump.c |
|
mbr.bin: mbr.o |
$(BUILD)/bin/ld -h -rc 0xC0010000 -o mbr.bin mbr.o |
|
mbr.o: mbr.s |
$(BUILD)/bin/as -o mbr.o mbr.s |
|
clean: |
rm -f *~ dump mbr.o mbr.bin mbr.dump |
/mbr/mbr.s
0,0 → 1,54
; |
; mbr.s -- the master boot record |
; |
|
.set tba,0xF0300000 ; terminal base address |
.set tos,0xC0011000 ; top of stack |
|
start: |
add $29,$0,tos ; set stackpointer |
jal msgout ; output message |
stop: |
j stop ; halt by looping |
|
msgout: |
sub $29,$29,8 ; allocate stack frame |
stw $31,$29,0 ; save return register |
stw $16,$29,4 ; save local variable |
add $16,$0,msg ; pointer to string |
loop: |
ldbu $4,$16,0 ; get char |
beq $4,$0,exit ; null - finished |
jal out ; output char |
add $16,$16,1 ; bump pointer |
j loop ; next char |
exit: |
ldw $31,$29,0 ; restore return register |
ldw $16,$29,4 ; restore local variable |
add $29,$29,8 ; release stack frame |
jr $31 ; return |
|
out: |
add $8,$0,tba ; set I/O base address |
out1: |
ldw $9,$8,8 ; get xmtr status |
and $9,$9,1 ; xmtr ready? |
beq $9,$0,out1 ; no - wait |
stw $4,$8,12 ; send char |
jr $31 ; return |
|
msg: |
.byte 0x0D, 0x0A |
.byte "Error: This is the default MBR, " |
.byte "which cannot load anything." |
.byte 0x0D, 0x0A |
.byte "Please replace the disk, or " |
.byte "write an operating system onto it." |
.byte 0x0D, 0x0A |
.byte "Execution halted." |
.byte 0x0D, 0x0A |
.byte 0x0D, 0x0A, 0 |
|
.locate 512-2 |
sign: |
.byte 0x55, 0xAA |
/mbr/dump.c
0,0 → 1,48
/* |
* dump.c -- dump a binary file as contents of a C array |
*/ |
|
|
#include <stdio.h> |
#include <stdlib.h> |
#include <string.h> |
|
|
int main(int argc, char *argv[]) { |
FILE *infile, *outfile; |
int c, n; |
|
if (argc != 3) { |
printf("Usage: %s <infile> <outfile>\n", argv[0]); |
return 1; |
} |
infile = fopen(argv[1], "rb"); |
if (infile == NULL) { |
printf("Error: cannot open file '%s' for input\n", argv[1]); |
return 1; |
} |
outfile = fopen(argv[2], "wt"); |
if (outfile == NULL) { |
printf("Error: cannot open file '%s' for output\n", argv[2]); |
return 1; |
} |
n = 0; |
while (1) { |
c = getc(infile); |
if (c == EOF) { |
break; |
} |
fprintf(outfile, "0x%02X, ", c); |
n++; |
if (n == 8) { |
n = 0; |
fprintf(outfile, "\n"); |
} |
} |
if (n != 0) { |
fprintf(outfile, "\n"); |
} |
fclose(infile); |
fclose(outfile); |
return 0; |
} |
/Makefile
0,0 → 1,38
# |
# Makefile for "wrtmbr", a program to write a dummy MBR to the disk |
# |
|
BUILD = ../../build |
|
SRC = start.s main.c end.s |
BIN = wrtmbr.bin |
MAP = wrtmbr.map |
EXO = wrtmbr.exo |
|
.PHONY: all install run clean |
|
all: $(BIN) $(EXO) |
|
install: $(BIN) $(EXO) |
mkdir -p $(BUILD)/stdalone |
cp $(BIN) $(BUILD)/stdalone |
cp $(MAP) $(BUILD)/stdalone |
cp $(EXO) $(BUILD)/stdalone |
|
run: $(BIN) |
$(BUILD)/bin/sim -i -s 1 -t 0 -l $(BIN) -a 0x10000 \ |
-d $(BUILD)/run/disk.img |
|
$(EXO): $(BIN) |
$(BUILD)/bin/bin2exo -S2 0x10000 $(BIN) $(EXO) |
|
$(BIN): $(SRC) mbr/mbr.dump |
$(BUILD)/bin/lcc -A -Wo-kernel \ |
-Wl-m -Wl$(MAP) -o $(BIN) $(SRC) |
|
mbr/mbr.dump: |
$(MAKE) -C mbr |
|
clean: |
$(MAKE) -C mbr clean |
rm -f *~ $(BIN) $(MAP) $(EXO) |
/start.s
0,0 → 1,218
; |
; start.s -- startup code |
; |
|
.import main |
.import _ecode |
.import _edata |
.import _ebss |
|
.export _bcode |
.export _bdata |
.export _bbss |
|
.export enable |
.export disable |
.export getISR |
.export setISR |
|
.code |
_bcode: |
|
.data |
_bdata: |
|
.bss |
_bbss: |
|
.code |
|
; reset arrives here |
reset: |
j start |
|
; interrupts arrive here |
intrpt: |
j isr |
|
; user TLB misses arrive here |
userMiss: |
j userMiss |
|
isr: |
add $26,$29,$0 ; sp -> $26 |
add $27,$1,$0 ; $1 -> $27 |
add $29,$0,istack ; set stack |
sub $29,$29,108 |
stw $2,$29,0 ; save registers |
stw $3,$29,4 |
stw $4,$29,8 |
stw $5,$29,12 |
stw $6,$29,16 |
stw $7,$29,20 |
stw $8,$29,24 |
stw $9,$29,28 |
stw $10,$29,32 |
stw $11,$29,36 |
stw $12,$29,40 |
stw $13,$29,44 |
stw $14,$29,48 |
stw $15,$29,52 |
stw $16,$29,56 |
stw $17,$29,60 |
stw $18,$29,64 |
stw $19,$29,68 |
stw $20,$29,72 |
stw $21,$29,76 |
stw $22,$29,80 |
stw $23,$29,84 |
stw $24,$29,88 |
stw $25,$29,92 |
stw $26,$29,96 |
stw $27,$29,100 |
stw $31,$29,104 |
mvfs $4,0 ; $4 = IRQ number |
slr $4,$4,16 |
and $4,$4,0x1F |
sll $26,$4,2 ; $26 = 4 * IRQ number |
ldw $26,$26,irqsrv ; get addr of service routine |
jalr $26 ; call service routine |
beq $2,$0,resume ; resume instruction if ISR returned 0 |
add $30,$30,4 ; else skip offending instruction |
resume: |
ldw $2,$29,0 |
ldw $3,$29,4 |
ldw $4,$29,8 |
ldw $5,$29,12 |
ldw $6,$29,16 |
ldw $7,$29,20 |
ldw $8,$29,24 |
ldw $9,$29,28 |
ldw $10,$29,32 |
ldw $11,$29,36 |
ldw $12,$29,40 |
ldw $13,$29,44 |
ldw $14,$29,48 |
ldw $15,$29,52 |
ldw $16,$29,56 |
ldw $17,$29,60 |
ldw $18,$29,64 |
ldw $19,$29,68 |
ldw $20,$29,72 |
ldw $21,$29,76 |
ldw $22,$29,80 |
ldw $23,$29,84 |
ldw $24,$29,88 |
ldw $25,$29,92 |
ldw $26,$29,96 |
ldw $27,$29,100 |
ldw $31,$29,104 |
add $1,$27,$0 ; $27 -> $1 |
add $29,$26,0 ; $26 -> sp |
rfx ; return from exception |
|
start: |
add $8,$0,0xA8003FFF |
add $9,$0,0xC0000000 |
stw $8,$9,0 ; 0xC0000000: j 0xC0010000 |
stw $8,$9,4 ; 0xC0000004: j 0xC0010004 |
stw $8,$9,8 ; 0xC0000008: j 0xC0010008 |
mvfs $8,0 |
or $8,$8,1 << 27 ; let vector point to RAM |
mvts $8,0 |
add $29,$0,stack ; set sp |
add $10,$0,_bdata ; copy data segment |
add $8,$0,_edata |
sub $9,$8,$10 |
add $9,$9,_ecode |
j cpytest |
cpyloop: |
ldw $11,$9,0 |
stw $11,$8,0 |
cpytest: |
sub $8,$8,4 |
sub $9,$9,4 |
bgeu $8,$10,cpyloop |
add $8,$0,_bbss ; clear bss |
add $9,$0,_ebss |
j clrtest |
clrloop: |
stw $0,$8,0 |
add $8,$8,4 |
clrtest: |
bltu $8,$9,clrloop |
jal main ; call 'main' |
start1: |
j start1 ; loop |
|
enable: |
mvfs $8,0 |
or $8,$8,1 << 23 |
mvts $8,0 |
jr $31 |
|
disable: |
mvfs $8,0 |
and $8,$8,~(1 << 23) |
mvts $8,0 |
jr $31 |
|
getISR: |
sll $4,$4,2 |
ldw $2,$4,irqsrv |
jr $31 |
|
setISR: |
sll $4,$4,2 |
stw $5,$4,irqsrv |
jr $31 |
|
.data |
|
; interrupt service routine table |
|
.align 4 |
|
irqsrv: |
.word 0 ; 00: terminal 0 transmitter interrupt |
.word 0 ; 01: terminal 0 receiver interrupt |
.word 0 ; 02: terminal 1 transmitter interrupt |
.word 0 ; 03: terminal 1 receiver interrupt |
.word 0 ; 04: keyboard interrupt |
.word 0 ; 05: unused |
.word 0 ; 06: unused |
.word 0 ; 07: unused |
.word 0 ; 08: disk interrupt |
.word 0 ; 09: unused |
.word 0 ; 10: unused |
.word 0 ; 11: unused |
.word 0 ; 12: unused |
.word 0 ; 13: unused |
.word 0 ; 14: timer 0 interrupt |
.word 0 ; 15: timer 1 interrupt |
.word 0 ; 16: bus timeout exception |
.word 0 ; 17: illegal instruction exception |
.word 0 ; 18: privileged instruction exception |
.word 0 ; 19: divide instruction exception |
.word 0 ; 20: trap instruction exception |
.word 0 ; 21: TLB miss exception |
.word 0 ; 22: TLB write exception |
.word 0 ; 23: TLB invalid exception |
.word 0 ; 24: illegal address exception |
.word 0 ; 25: privileged address exception |
.word 0 ; 26: unused |
.word 0 ; 27: unused |
.word 0 ; 28: unused |
.word 0 ; 29: unused |
.word 0 ; 30: unused |
.word 0 ; 31: unused |
|
.bss |
|
.align 4 |
.space 0x800 |
stack: |
|
.align 4 |
.space 0x800 |
istack: |
/main.c
0,0 → 1,312
/* |
* main.c -- start the ball rolling |
*/ |
|
|
#include "stdarg.h" |
#include "start.h" |
|
|
#define SCT_SIZE 512 /* in bytes */ |
|
#define DISK_BASE 0xF0400000 |
|
#define DISK_CTRL 0 /* word offset from DISK_BASE */ |
#define DISK_CNT 1 /* ditto */ |
#define DISK_SCT 2 /* ditto */ |
#define DISK_CAP 3 /* ditto */ |
|
#define DISK_BUF_STRT 0x00020000 /* word offset from DISK_BASE */ |
#define DISK_BUF_SIZE 0x00000400 /* in words */ |
|
#define DISK_CTRL_STRT 0x01 |
#define DISK_CTRL_IEN 0x02 |
#define DISK_CTRL_WRT 0x04 |
#define DISK_CTRL_ERR 0x08 |
#define DISK_CTRL_DONE 0x10 |
#define DISK_CTRL_RDY 0x20 |
|
|
/**************************************************************/ |
|
|
void putchar(char c) { |
unsigned int *base; |
|
if (c == '\n') { |
putchar('\r'); |
} |
base = (unsigned int *) 0xF0300000; |
while ((*(base + 2) & 1) == 0) ; |
*(base + 3) = c; |
} |
|
|
void puts(char *s) { |
char c; |
|
while ((c = *s++) != '\0') { |
putchar(c); |
} |
} |
|
|
void printn(int n) { |
int a; |
|
if (n < 0) { |
putchar('-'); |
n = -n; |
} |
a = n / 10; |
if (a != 0) { |
printn(a); |
} |
putchar(n % 10 + '0'); |
} |
|
|
void printu(unsigned int n, unsigned int b) { |
unsigned int a; |
|
a = n / b; |
if (a != 0) { |
printu(a, b); |
} |
putchar("0123456789ABCDEF"[n % b]); |
} |
|
|
void printf(char *fmt, ...) { |
va_list ap; |
char c; |
int n; |
unsigned int u; |
char *s; |
|
va_start(ap, fmt); |
while (1) { |
while ((c = *fmt++) != '%') { |
if (c == '\0') { |
va_end(ap); |
return; |
} |
putchar(c); |
} |
c = *fmt++; |
if (c == 'd') { |
n = va_arg(ap, int); |
printn(n); |
} else |
if (c == 'u' || c == 'o' || c == 'x') { |
u = va_arg(ap, int); |
printu(u, c == 'o' ? 8 : (c == 'x' ? 16 : 10)); |
} else |
if (c == 's') { |
s = va_arg(ap, char *); |
puts(s); |
} else { |
putchar(c); |
} |
} |
} |
|
|
/**************************************************************/ |
|
|
static char *exceptionCause[32] = { |
/* 00 */ "terminal 0 transmitter interrupt", |
/* 01 */ "terminal 0 receiver interrupt", |
/* 02 */ "terminal 1 transmitter interrupt", |
/* 03 */ "terminal 1 receiver interrupt", |
/* 04 */ "keyboard interrupt", |
/* 05 */ "unknown interrupt", |
/* 06 */ "unknown interrupt", |
/* 07 */ "unknown interrupt", |
/* 08 */ "disk interrupt", |
/* 09 */ "unknown interrupt", |
/* 10 */ "unknown interrupt", |
/* 11 */ "unknown interrupt", |
/* 12 */ "unknown interrupt", |
/* 13 */ "unknown interrupt", |
/* 14 */ "timer 0 interrupt", |
/* 15 */ "timer 1 interrupt", |
/* 16 */ "bus timeout exception", |
/* 17 */ "illegal instruction exception", |
/* 18 */ "privileged instruction exception", |
/* 19 */ "divide instruction exception", |
/* 20 */ "trap instruction exception", |
/* 21 */ "TLB miss exception", |
/* 22 */ "TLB write exception", |
/* 23 */ "TLB invalid exception", |
/* 24 */ "illegal address exception", |
/* 25 */ "privileged address exception", |
/* 26 */ "unknown exception", |
/* 27 */ "unknown exception", |
/* 28 */ "unknown exception", |
/* 29 */ "unknown exception", |
/* 30 */ "unknown exception", |
/* 31 */ "unknown exception" |
}; |
|
|
int defaultISR(int irq) { |
printf("\n%s\n", exceptionCause[irq]); |
return 0; /* do not skip any instruction */ |
} |
|
|
void initInterrupts(void) { |
int i; |
|
for (i = 0; i < 32; i++) { |
setISR(i, defaultISR); |
} |
} |
|
|
/**************************************************************/ |
|
|
/* the MBR buffer need not be word-aligned */ |
unsigned char mbr[SCT_SIZE] = { |
#include "mbr/mbr.dump" |
}; |
|
/* the following two buffers must be word-aligned */ |
unsigned int wrBuf[SCT_SIZE / sizeof(unsigned int)]; |
unsigned int rdBuf[SCT_SIZE / sizeof(unsigned int)]; |
|
|
void copyMBR(void) { |
unsigned char *p; |
unsigned char *q; |
int i; |
|
p = (unsigned char *) wrBuf; |
q = (unsigned char *) mbr; |
for (i = 0; i < SCT_SIZE; i++) { |
*p++ = *q++; |
} |
} |
|
|
int compareMBR(void) { |
unsigned char *p; |
unsigned char *q; |
int i; |
|
p = (unsigned char *) rdBuf; |
q = (unsigned char *) mbr; |
for (i = 0; i < SCT_SIZE; i++) { |
if (*p++ != *q++) { |
return 0; |
} |
} |
return 1; |
} |
|
|
void clearCtrl(void) { |
unsigned int *p; |
int i; |
|
p = (unsigned int *) DISK_BASE + DISK_BUF_STRT; |
for (i = 0; i < DISK_BUF_SIZE; i++) { |
*p++ = 0; |
} |
} |
|
|
void copyToCtrl(void) { |
unsigned int *p; |
unsigned int *q; |
int i; |
|
p = (unsigned int *) DISK_BASE + DISK_BUF_STRT; |
q = (unsigned int *) wrBuf; |
for (i = 0; i < SCT_SIZE / sizeof(unsigned int); i++) { |
*p++ = *q++; |
} |
} |
|
|
void copyFromCtrl(void) { |
unsigned int *p; |
unsigned int *q; |
int i; |
|
p = (unsigned int *) rdBuf; |
q = (unsigned int *) DISK_BASE + DISK_BUF_STRT; |
for (i = 0; i < SCT_SIZE / sizeof(unsigned int); i++) { |
*p++ = *q++; |
} |
} |
|
|
int checkDiskReady(void) { |
unsigned int *p; |
int tries; |
int i; |
|
p = (unsigned int *) DISK_BASE; |
for (tries = 0; tries < 10; tries++) { |
for (i = 0; i < 500000; i++) { |
if ((*(p + DISK_CTRL) & DISK_CTRL_RDY) != 0) { |
return 1; |
} |
} |
printf("."); |
} |
return 0; |
} |
|
|
void writeMBR(void) { |
unsigned int *p; |
|
p = (unsigned int *) DISK_BASE; |
*(p + DISK_CNT) = 1; |
*(p + DISK_SCT) = 0; |
*(p + DISK_CTRL) = DISK_CTRL_WRT | DISK_CTRL_STRT; |
while ((*(p + DISK_CTRL) & DISK_CTRL_DONE) == 0) ; |
} |
|
|
void readMBR(void) { |
unsigned int *p; |
|
p = (unsigned int *) DISK_BASE; |
*(p + DISK_CNT) = 1; |
*(p + DISK_SCT) = 0; |
*(p + DISK_CTRL) = DISK_CTRL_STRT; |
while ((*(p + DISK_CTRL) & DISK_CTRL_DONE) == 0) ; |
} |
|
|
void main(void) { |
initInterrupts(); |
printf("Checking disk ready..."); |
if (!checkDiskReady()) { |
printf(" disk not ready\n"); |
} else { |
printf(" ok\n"); |
printf("Writing MBR...\n"); |
copyMBR(); |
clearCtrl(); |
copyToCtrl(); |
writeMBR(); |
printf("Reading MBR...\n"); |
clearCtrl(); |
readMBR(); |
copyFromCtrl(); |
printf("Comparing MBR..."); |
if (!compareMBR()) { |
printf(" error\n"); |
} else { |
printf(" ok\n"); |
} |
} |
printf("Halting...\n"); |
} |
/start.h
0,0 → 1,19
/* |
* start.h -- startup code |
*/ |
|
|
#ifndef _START_H_ |
#define _START_H_ |
|
|
typedef int (*ISR)(int irq); |
|
|
void enable(void); |
void disable(void); |
ISR getISR(int irq); |
void setISR(int irq, ISR isr); |
|
|
#endif /* _START_H_ */ |
/end.s
0,0 → 1,19
; |
; end.s -- end-of-segment labels |
; |
|
.export _ecode |
.export _edata |
.export _ebss |
|
.code |
.align 4 |
_ecode: |
|
.data |
.align 4 |
_edata: |
|
.bss |
.align 4 |
_ebss: |
/stdarg.h
0,0 → 1,41
/* |
* stdarg.h -- variable argument lists |
*/ |
|
|
#ifndef _STDARG_H_ |
#define _STDARG_H_ |
|
|
typedef char *va_list; |
|
|
static float __va_arg_tmp; |
|
|
#define va_start(list, start) \ |
((void)((list) = (sizeof(start)<4 ? \ |
(char *)((int *)&(start)+1) : (char *)(&(start)+1)))) |
|
#define __va_arg(list, mode, n) \ |
(__typecode(mode)==1 && sizeof(mode)==4 ? \ |
(__va_arg_tmp = *(double *)(&(list += \ |
((sizeof(double)+n)&~n))[-(int)((sizeof(double)+n)&~n)]), \ |
*(mode *)&__va_arg_tmp) : \ |
*(mode *)(&(list += \ |
((sizeof(mode)+n)&~n))[-(int)((sizeof(mode)+n)&~n)])) |
|
#define _bigendian_va_arg(list, mode, n) \ |
(sizeof(mode)==1 ? *(mode *)(&(list += 4)[-1]) : \ |
sizeof(mode)==2 ? *(mode *)(&(list += 4)[-2]) : \ |
__va_arg(list, mode, n)) |
|
#define va_end(list) ((void)0) |
|
#define va_arg(list, mode) \ |
(sizeof(mode)==8 ? \ |
*(mode *)(&(list = (char*)(((int)list + 15)&~7U))[-8]) : \ |
_bigendian_va_arg(list, mode, 3U)) |
|
|
#endif /* _STDARG_H_ */ |