Add --boot-from-serial option

The emulator does not require a disk image when using this option. The
firmware however will attempt to initialize the SD cards regardless of
chosen boot method, so we still emulate a dummy SD card.
This commit is contained in:
Peter De Wachter 2017-10-25 20:39:03 +02:00
parent 08248b93fa
commit a0890e1b40
4 changed files with 59 additions and 29 deletions

View File

@ -32,6 +32,7 @@ struct Disk {
static uint32_t disk_read(const struct RISC_SPI *spi);
static void disk_write(const struct RISC_SPI *spi, uint32_t value);
static void disk_run_command(struct Disk *disk);
static void seek_sector(FILE *f, uint32_t secnum);
static void read_sector(FILE *f, uint32_t buf[static 128]);
static void write_sector(FILE *f, uint32_t buf[static 128]);
@ -45,15 +46,17 @@ struct RISC_SPI *disk_new(const char *filename) {
disk->state = diskCommand;
disk->file = fopen(filename, "rb+");
if (disk->file == 0) {
fprintf(stderr, "Can't open file \"%s\": %s\n", filename, strerror(errno));
exit(1);
}
if (filename) {
disk->file = fopen(filename, "rb+");
if (disk->file == 0) {
fprintf(stderr, "Can't open file \"%s\": %s\n", filename, strerror(errno));
exit(1);
}
// Check for filesystem-only image, starting directly at sector 1 (DiskAdr 29)
read_sector(disk->file, &disk->tx_buf[0]);
disk->offset = (disk->tx_buf[0] == 0x9B1EA38D)? 0x80002 : 0;
// Check for filesystem-only image, starting directly at sector 1 (DiskAdr 29)
read_sector(disk->file, &disk->tx_buf[0]);
disk->offset = (disk->tx_buf[0] == 0x9B1EA38D) ? 0x80002 : 0;
}
return &disk->spi;
}
@ -130,14 +133,14 @@ static void disk_run_command(struct Disk *disk) {
disk->state = diskRead;
disk->tx_buf[0] = 0;
disk->tx_buf[1] = 254;
fseek(disk->file, (arg - disk->offset) * 512, SEEK_SET);
seek_sector(disk->file, arg - disk->offset);
read_sector(disk->file, &disk->tx_buf[2]);
disk->tx_cnt = 2 + 128;
break;
}
case 88: {
disk->state = diskWrite;
fseek(disk->file, (arg - disk->offset) * 512, SEEK_SET);
seek_sector(disk->file, arg - disk->offset);
disk->tx_buf[0] = 0;
disk->tx_cnt = 1;
break;
@ -151,9 +154,17 @@ static void disk_run_command(struct Disk *disk) {
disk->tx_idx = -1;
}
static void seek_sector(FILE *f, uint32_t secnum) {
if (f) {
fseek(f, secnum * 512, SEEK_SET);
}
}
static void read_sector(FILE *f, uint32_t buf[static 128]) {
uint8_t bytes[512] = { 0 };
fread(bytes, 512, 1, f);
if (f) {
fread(bytes, 512, 1, f);
}
for (int i = 0; i < 128; i++) {
buf[i] = (uint32_t)bytes[i*4+0]
| ((uint32_t)bytes[i*4+1] << 8)
@ -163,12 +174,14 @@ static void read_sector(FILE *f, uint32_t buf[static 128]) {
}
static void write_sector(FILE *f, uint32_t buf[static 128]) {
uint8_t bytes[512];
for (int i = 0; i < 128; i++) {
bytes[i*4+0] = (uint8_t)(buf[i] );
bytes[i*4+1] = (uint8_t)(buf[i] >> 8);
bytes[i*4+2] = (uint8_t)(buf[i] >> 16);
bytes[i*4+3] = (uint8_t)(buf[i] >> 24);
if (f) {
uint8_t bytes[512];
for (int i = 0; i < 128; i++) {
bytes[i*4+0] = (uint8_t)(buf[i] );
bytes[i*4+1] = (uint8_t)(buf[i] >> 8);
bytes[i*4+2] = (uint8_t)(buf[i] >> 16);
bytes[i*4+3] = (uint8_t)(buf[i] >> 24);
}
fwrite(bytes, 512, 1, f);
}
fwrite(bytes, 512, 1, f);
}

View File

@ -39,6 +39,7 @@ struct RISC {
uint32_t mouse;
uint8_t key_buf[16];
uint32_t key_cnt;
uint32_t switches;
const struct RISC_LED *leds;
const struct RISC_Serial *serial;
@ -101,6 +102,10 @@ void risc_set_clipboard(struct RISC *risc, const struct RISC_Clipboard *clipboar
risc->clipboard = clipboard;
}
void risc_set_switches(struct RISC *risc, int switches) {
risc->switches = switches;
}
void risc_screen_size_hack(struct RISC *risc, int width, int height) {
risc->fb_width = width / 32;
risc->fb_height = height;
@ -407,7 +412,7 @@ static uint32_t risc_load_io(struct RISC *risc, uint32_t address) {
}
case 4: {
// Switches
return 0;
return risc->switches;
}
case 8: {
// RS232 data

View File

@ -20,6 +20,7 @@ void risc_set_leds(struct RISC *risc, const struct RISC_LED *leds);
void risc_set_serial(struct RISC *risc, const struct RISC_Serial *serial);
void risc_set_spi(struct RISC *risc, int index, const struct RISC_SPI *spi);
void risc_set_clipboard(struct RISC *risc, const struct RISC_Clipboard *clipboard);
void risc_set_switches(struct RISC *risc, int switches);
void risc_screen_size_hack(struct RISC *risc, int width, int height);
void risc_reset(struct RISC *risc);

View File

@ -62,13 +62,14 @@ struct KeyMapping key_map[] = {
};
static struct option long_options[] = {
{ "zoom", required_argument, NULL, 'z' },
{ "fullscreen", no_argument, NULL, 'f' },
{ "leds", no_argument, NULL, 'L' },
{ "size", required_argument, NULL, 's' },
{ "serial-in", required_argument, NULL, 'I' },
{ "serial-out", required_argument, NULL, 'O' },
{ NULL, no_argument, NULL, 0 }
{ "zoom", required_argument, NULL, 'z' },
{ "fullscreen", no_argument, NULL, 'f' },
{ "leds", no_argument, NULL, 'L' },
{ "size", required_argument, NULL, 's' },
{ "serial-in", required_argument, NULL, 'I' },
{ "serial-out", required_argument, NULL, 'O' },
{ "boot-from-serial", no_argument, NULL, 'S' },
{ NULL, no_argument, NULL, 0 }
};
static void fail(int code, const char *fmt, ...) {
@ -101,9 +102,10 @@ int main (int argc, char *argv[]) {
};
const char *serial_in = NULL;
const char *serial_out = NULL;
bool boot_from_serial = false;
int opt;
while ((opt = getopt_long(argc, argv, "z:fLS:I:O:", long_options, NULL)) != -1) {
while ((opt = getopt_long(argc, argv, "z:fLs:I:O:S", long_options, NULL)) != -1) {
switch (opt) {
case 'z': {
double x = strtod(optarg, 0);
@ -138,16 +140,25 @@ int main (int argc, char *argv[]) {
serial_out = optarg;
break;
}
case 'S': {
boot_from_serial = true;
risc_set_switches(risc, 1);
break;
}
default: {
usage();
}
}
}
if (optind != argc - 1) {
if (optind == argc - 1) {
risc_set_spi(risc, 1, disk_new(argv[optind]));
} else if (optind == argc && boot_from_serial) {
/* Allow diskless boot */
risc_set_spi(risc, 1, disk_new(NULL));
} else {
usage();
}
risc_set_spi(risc, 1, disk_new(argv[optind]));
if (serial_in || serial_out) {
if (!serial_in) {