/*
|
/*
|
* mboot.c -- the master bootstrap (boot manager)
|
* mboot.c -- the master bootstrap (boot manager)
|
*/
|
*/
|
|
|
|
|
#include "stdarg.h"
|
#include "stdarg.h"
|
#include "biolib.h"
|
#include "biolib.h"
|
|
|
|
|
#define DEFAULT_PARTITION "" /* default boot partition number */
|
#define DEFAULT_PARTITION "" /* default boot partition number */
|
|
|
#define LOAD_ADDR 0xC0010000
|
#define LOAD_ADDR 0xC0010000
|
|
|
#define LINE_SIZE 80
|
#define LINE_SIZE 80
|
#define SECTOR_SIZE 512
|
#define SECTOR_SIZE 512
|
#define NPE (SECTOR_SIZE / sizeof(PartEntry))
|
#define NPE (SECTOR_SIZE / sizeof(PartEntry))
|
#define DESCR_SIZE 20
|
#define DESCR_SIZE 20
|
|
|
|
|
unsigned int bootDisk = 0; /* gets loaded by previous stage */
|
unsigned int bootDisk = 0; /* gets loaded by previous stage */
|
unsigned int startSector = 0; /* gets loaded by previous stage */
|
unsigned int startSector = 0; /* gets loaded by previous stage */
|
unsigned int numSectors = 0; /* gets loaded by previous stage */
|
unsigned int numSectors = 0; /* gets loaded by previous stage */
|
|
|
|
|
typedef struct {
|
typedef struct {
|
unsigned int type;
|
unsigned int type;
|
unsigned int start;
|
unsigned int start;
|
unsigned int size;
|
unsigned int size;
|
char descr[DESCR_SIZE];
|
char descr[DESCR_SIZE];
|
} PartEntry;
|
} PartEntry;
|
|
|
PartEntry ptr[NPE];
|
PartEntry ptr[NPE];
|
|
|
|
|
int strlen(char *str) {
|
int strlen(char *str) {
|
int i;
|
int i;
|
|
|
i = 0;
|
i = 0;
|
while (*str++ != '\0') {
|
while (*str++ != '\0') {
|
i++;
|
i++;
|
}
|
}
|
return i;
|
return i;
|
}
|
}
|
|
|
|
|
void strcpy(char *dst, char *src) {
|
void strcpy(char *dst, char *src) {
|
while ((*dst++ = *src++) != '\0') ;
|
while ((*dst++ = *src++) != '\0') ;
|
}
|
}
|
|
|
|
|
char getchar(void) {
|
char getchar(void) {
|
return getc();
|
return getc();
|
}
|
}
|
|
|
|
|
void putchar(char c) {
|
void putchar(char c) {
|
if (c == '\n') {
|
if (c == '\n') {
|
putchar('\r');
|
putchar('\r');
|
}
|
}
|
putc(c);
|
putc(c);
|
}
|
}
|
|
|
|
|
void puts(char *s) {
|
void puts(char *s) {
|
char c;
|
char c;
|
|
|
while ((c = *s++) != '\0') {
|
while ((c = *s++) != '\0') {
|
putchar(c);
|
putchar(c);
|
}
|
}
|
}
|
}
|
|
|
|
|
void getline(char *prompt, char *line, int n) {
|
void getline(char *prompt, char *line, int n) {
|
int i;
|
int i;
|
char c;
|
char c;
|
|
|
puts(prompt);
|
puts(prompt);
|
puts(line);
|
puts(line);
|
i = strlen(line);
|
i = strlen(line);
|
while (i < n - 1) {
|
while (i < n - 1) {
|
c = getchar();
|
c = getchar();
|
if (c >= ' ' && c < 0x7F) {
|
if (c >= ' ' && c < 0x7F) {
|
putchar(c);
|
putchar(c);
|
line[i] = c;
|
line[i] = c;
|
i++;
|
i++;
|
} else
|
} else
|
if (c == '\r') {
|
if (c == '\r') {
|
putchar('\n');
|
putchar('\n');
|
line[i] = '\0';
|
line[i] = '\0';
|
i = n - 1;
|
i = n - 1;
|
} else
|
} else
|
if (c == '\b' || c == 0x7F) {
|
if (c == '\b' || c == 0x7F) {
|
if (i > 0) {
|
if (i > 0) {
|
putchar('\b');
|
putchar('\b');
|
putchar(' ');
|
putchar(' ');
|
putchar('\b');
|
putchar('\b');
|
i--;
|
i--;
|
}
|
}
|
}
|
}
|
}
|
}
|
line[n - 1] = '\0';
|
line[n - 1] = '\0';
|
}
|
}
|
|
|
|
|
int countPrintn(long n) {
|
int countPrintn(int n) {
|
long a;
|
int a;
|
int res;
|
int res;
|
|
|
res = 0;
|
res = 0;
|
if (n < 0) {
|
if (n < 0) {
|
res++;
|
res++;
|
n = -n;
|
n = -n;
|
}
|
}
|
a = n / 10;
|
a = n / 10;
|
if (a != 0) {
|
if (a != 0) {
|
res += countPrintn(a);
|
res += countPrintn(a);
|
}
|
}
|
return res + 1;
|
return res + 1;
|
}
|
}
|
|
|
|
|
void printn(long n) {
|
void printn(int n) {
|
long a;
|
int a;
|
|
|
if (n < 0) {
|
if (n < 0) {
|
putchar('-');
|
putchar('-');
|
n = -n;
|
n = -n;
|
}
|
}
|
a = n / 10;
|
a = n / 10;
|
if (a != 0) {
|
if (a != 0) {
|
printn(a);
|
printn(a);
|
}
|
}
|
putchar(n % 10 + '0');
|
putchar(n % 10 + '0');
|
}
|
}
|
|
|
|
|
void printf(char *fmt, ...) {
|
void printf(char *fmt, ...) {
|
va_list ap;
|
va_list ap;
|
char c;
|
char c;
|
int n;
|
int n;
|
unsigned int u;
|
unsigned int u;
|
char *s;
|
char *s;
|
char filler;
|
char filler;
|
int width, count, i;
|
int width, count, i;
|
|
|
va_start(ap, fmt);
|
va_start(ap, fmt);
|
while (1) {
|
while (1) {
|
while ((c = *fmt++) != '%') {
|
while ((c = *fmt++) != '%') {
|
if (c == '\0') {
|
if (c == '\0') {
|
va_end(ap);
|
va_end(ap);
|
return;
|
return;
|
}
|
}
|
putchar(c);
|
putchar(c);
|
}
|
}
|
c = *fmt++;
|
c = *fmt++;
|
if (c == '0') {
|
if (c == '0') {
|
filler = '0';
|
filler = '0';
|
c = *fmt++;
|
c = *fmt++;
|
} else {
|
} else {
|
filler = ' ';
|
filler = ' ';
|
}
|
}
|
width = 0;
|
width = 0;
|
if (c >= '0' && c <= '9') {
|
if (c >= '0' && c <= '9') {
|
width = c - '0';
|
width = c - '0';
|
c = *fmt++;
|
c = *fmt++;
|
}
|
}
|
if (c == 'd') {
|
if (c == 'd') {
|
n = va_arg(ap, int);
|
n = va_arg(ap, int);
|
if (width > 0) {
|
if (width > 0) {
|
count = countPrintn(n);
|
count = countPrintn(n);
|
for (i = 0; i < width - count; i++) {
|
for (i = 0; i < width - count; i++) {
|
putchar(filler);
|
putchar(filler);
|
}
|
}
|
}
|
}
|
printn(n);
|
printn(n);
|
} else
|
} else
|
if (c == 's') {
|
if (c == 's') {
|
s = va_arg(ap, char *);
|
s = va_arg(ap, char *);
|
puts(s);
|
puts(s);
|
} else
|
} else
|
if (c == 'c') {
|
if (c == 'c') {
|
c = va_arg(ap, char);
|
c = va_arg(ap, char);
|
putchar(c);
|
putchar(c);
|
} else {
|
} else {
|
putchar(c);
|
putchar(c);
|
}
|
}
|
}
|
}
|
}
|
}
|
|
|
|
|
void halt(void) {
|
void halt(void) {
|
printf("bootstrap halted\n");
|
printf("bootstrap halted\n");
|
while (1) ;
|
while (1) ;
|
}
|
}
|
|
|
|
|
void readDisk(unsigned int sector, unsigned char *buffer, int count) {
|
void readDisk(unsigned int sector, unsigned char *buffer, int count) {
|
int result;
|
int result;
|
|
|
if (sector + count > numSectors) {
|
if (sector + count > numSectors) {
|
printf("sector number exceeds disk or partition size\n");
|
printf("sector number exceeds disk or partition size\n");
|
halt();
|
halt();
|
}
|
}
|
result = rwscts(bootDisk, 'r', sector + startSector,
|
result = rwscts(bootDisk, 'r', sector + startSector,
|
(unsigned int) buffer & 0x3FFFFFFF, count);
|
(unsigned int) buffer & 0x3FFFFFFF, count);
|
if (result != 0) {
|
if (result != 0) {
|
printf("disk read error\n");
|
printf("disk read error\n");
|
halt();
|
halt();
|
}
|
}
|
}
|
}
|
|
|
|
|
unsigned int entryPoint; /* where to continue from main() */
|
unsigned int entryPoint; /* where to continue from main() */
|
|
|
|
|
int main(void) {
|
int main(void) {
|
int i;
|
int i;
|
char line[LINE_SIZE];
|
char line[LINE_SIZE];
|
char *p;
|
char *p;
|
int part;
|
int part;
|
|
|
printf("Bootstrap manager executing...\n");
|
printf("Bootstrap manager executing...\n");
|
strcpy(line, DEFAULT_PARTITION);
|
strcpy(line, DEFAULT_PARTITION);
|
readDisk(1, (unsigned char *) ptr, 1);
|
readDisk(1, (unsigned char *) ptr, 1);
|
while (1) {
|
while (1) {
|
printf("\nPartitions:\n");
|
printf("\nPartitions:\n");
|
printf(" # | b | description\n");
|
printf(" # | b | description\n");
|
printf("---+---+----------------------\n");
|
printf("---+---+----------------------\n");
|
for (i = 0; i < NPE; i++) {
|
for (i = 0; i < NPE; i++) {
|
if (ptr[i].type != 0) {
|
if (ptr[i].type != 0) {
|
printf("%2d | %s | %s\n",
|
printf("%2d | %s | %s\n",
|
i, ptr[i].type & 0x80000000 ? "*" : " ", ptr[i].descr);
|
i, ptr[i].type & 0x80000000 ? "*" : " ", ptr[i].descr);
|
}
|
}
|
}
|
}
|
getline("\nBoot partition #: ", line, LINE_SIZE);
|
getline("\nBoot partition #: ", line, LINE_SIZE);
|
part = 0;
|
part = 0;
|
if (line[0] == '\0') {
|
if (line[0] == '\0') {
|
continue;
|
continue;
|
}
|
}
|
p = line;
|
p = line;
|
while (*p >= '0' && *p <= '9') {
|
while (*p >= '0' && *p <= '9') {
|
part = part * 10 + (*p - '0');
|
part = part * 10 + (*p - '0');
|
p++;
|
p++;
|
}
|
}
|
if (*p != '\0' || part < 0 || part > 15) {
|
if (*p != '\0' || part < 0 || part > 15) {
|
printf("illegal partition number\n");
|
printf("illegal partition number\n");
|
continue;
|
continue;
|
}
|
}
|
if ((ptr[part].type & 0x7FFFFFFF) == 0) {
|
if ((ptr[part].type & 0x7FFFFFFF) == 0) {
|
printf("partition %d does not contain a file system\n", part);
|
printf("partition %d does not contain a file system\n", part);
|
continue;
|
continue;
|
}
|
}
|
if ((ptr[part].type & 0x80000000) == 0) {
|
if ((ptr[part].type & 0x80000000) == 0) {
|
printf("partition %d is not bootable\n", part);
|
printf("partition %d is not bootable\n", part);
|
continue;
|
continue;
|
}
|
}
|
/* load boot sector of selected partition */
|
/* load boot sector of selected partition */
|
readDisk(ptr[part].start, (unsigned char *) LOAD_ADDR, 1);
|
readDisk(ptr[part].start, (unsigned char *) LOAD_ADDR, 1);
|
/* check for signature */
|
/* check for signature */
|
if ((*((unsigned char *) LOAD_ADDR + SECTOR_SIZE - 2) != 0x55) ||
|
if ((*((unsigned char *) LOAD_ADDR + SECTOR_SIZE - 2) != 0x55) ||
|
(*((unsigned char *) LOAD_ADDR + SECTOR_SIZE - 1) != 0xAA)) {
|
(*((unsigned char *) LOAD_ADDR + SECTOR_SIZE - 1) != 0xAA)) {
|
printf("boot sector of partition %d has no signature\n", part);
|
printf("boot sector of partition %d has no signature\n", part);
|
continue;
|
continue;
|
}
|
}
|
/* we have a valid boot sector, leave loop */
|
/* we have a valid boot sector, leave loop */
|
break;
|
break;
|
}
|
}
|
/* boot manager finished, now go executing loaded boot sector */
|
/* boot manager finished, now go executing loaded boot sector */
|
startSector = ptr[part].start;
|
startSector = ptr[part].start;
|
numSectors = ptr[part].size;
|
numSectors = ptr[part].size;
|
entryPoint = LOAD_ADDR;
|
entryPoint = LOAD_ADDR;
|
return 0;
|
return 0;
|
}
|
}
|
|
|