MKBOOT command

Added a MKBOOT command. It's able to zero out an MBR and write a boot sector that should load a file, but the system is not booting from it yet.
This commit is contained in:
Peter Weingartner 2022-03-24 21:05:27 -04:00
parent a9fa53550d
commit e8fe454513
9 changed files with 14180 additions and 13777 deletions

View file

@ -4,9 +4,12 @@
* Routines to support the boot process
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "boot.h"
#include "constants.h"
#include "errors.h"
#include "gabe_reg.h"
#include "log.h"
#include "simpleio.h"
@ -23,7 +26,7 @@
#include "rsrc/bitmaps/splash_a2560k.h"
#endif
#define SPLASH_WAIT_SEC 15
#define SPLASH_WAIT_SEC 15 /* How many seconds to wait on the splash screen */
/*
* Important scan codes
@ -35,11 +38,14 @@
#define SC_RETURN 0x1C
/* TODO: move this to constants.h */
#define MAX_PATH_LEN 256
#define BOOT_SECTOR_BUFFER ((volatile unsigned char *)0x00004000)
#define BOOT_SECTOR_VBR_OFF 0x060
#define BOOT_SECTOR_MBR_OFF 0x000
#define BOOT_CODE_MBR_OFF 0x000 /* Offset to the code in the MBR */
#define BOOT_CPUID_MBR_OFF 0x004 /* Offset to the CPUID in the MBR */
#define BOOT_SIG_MBR_OFF 0x006 /* Offset to the boot signature in the MBR */
#define BOOT_SIG 0xF0E1 /* Foenix/MCP boot signature expected */
const char * MCP_INIT_SDC = "/sd/system/mcp.init"; /**< Path to config file on the SD card */
const char * MCP_INIT_FDC = "/fd/system/mcp.init"; /**< Path to config file on the floppy drive */
@ -83,21 +89,32 @@ void cli_command_get(char * path) {
* @return 0 if not bootable, non-zero if bootable
*/
short is_bootable(unsigned short * sector, short device) {
short bootable = 0;
switch(device) {
case BDEV_FDC:
case BDEV_SDC:
// TODO: handled floppy drives
break;
case BDEV_SDC:
case BDEV_HDC:
// The SDC and HDC boot off the MBR...
// Check for the CPUID and boot signature
if ((sector[BOOT_CPUID_MBR_OFF] == CPU_M68000) ||
(sector[BOOT_CPUID_MBR_OFF] == CPU_M68040)) {
if ((sector[BOOT_SIG_MBR_OFF] == ((BOOT_SIG >> 8) & 0x00FF)) &&
(sector[BOOT_SIG_MBR_OFF+1] == (BOOT_SIG & 0x00FF))) {
// The CPU is supported, and the boot signature is correct
return 1;
}
}
break;
default:
// Otherwise: we're not bootable
break;
}
return bootable;
// If we have reached this point, the sector is not bootable
return 0;
}
/**
@ -106,17 +123,17 @@ short is_bootable(unsigned short * sector, short device) {
* @param device the number of the block device for the sector
*/
void boot_sector_run(short device) {
FUNC_V_2_V boot_sector = (FUNC_V_2_V)(BOOT_SECTOR_BUFFER + 0x060);
FUNC_V_2_V boot_sector = 0;
switch(device) {
case BDEV_FDC:
case BDEV_SDC:
boot_sector = (FUNC_V_2_V)(BOOT_SECTOR_BUFFER + BOOT_SECTOR_VBR_OFF);
boot_sector();
// TODO: support floppy drives
break;
case BDEV_SDC:
case BDEV_HDC:
boot_sector = (FUNC_V_2_V)(BOOT_SECTOR_BUFFER + BOOT_SECTOR_MBR_OFF);
// The SDC and HDC both boot off the MBR
boot_sector = (FUNC_V_2_V)(BOOT_SECTOR_BUFFER);
boot_sector();
break;
@ -328,22 +345,21 @@ void boot_from_bdev(short device) {
break;
}
// if (device >= 0) {
// // Try to load the boot sector
// short result = bdev_read(device, 0, BOOT_SECTOR_BUFFER, 512);
// if (result == 0) {
// // Check to see if it's bootable
// switch (device) {
// bootable = is_bootable(BOOT_SECTOR_BUFFER, device);
// }
// }
// }
if (device >= 0) {
// Try to load the boot sector
short result = bdev_read(device, 0, BOOT_SECTOR_BUFFER, 512);
if (result == 0) {
// Check to see if it's bootable
bootable = is_bootable(BOOT_SECTOR_BUFFER, device);
}
}
// if (bootable) {
// // If bootable, run it
// boot_sector_run(device);
//
// } else {
if (bootable) {
// If bootable, run it
print(cli_screen, "Running boot sector!\n");
boot_sector_run(device);
} else {
// If not bootable...
if (device >= 0) {
// Execute startup file on boot device (if present)
@ -381,5 +397,128 @@ void boot_from_bdev(short device) {
// No over-ride provided... boot the default
cli_repl(cli_screen);
}
// }
}
}
/**
* Make the indicated drive non booting by erasing the boot information
*
* @param device the number of the block device to use for booting (-1 to go straight to CLI)
* @return 0 on success, any other number is an error
*/
short boot_non_booting(short device) {
unsigned char * buffer;
short result = 0;
buffer = (unsigned char *)malloc(FSYS_SECTOR_SZ);
if (buffer != 0) {
// Try to read the current sector
short n = sys_bdev_read(device, 0, buffer, FSYS_SECTOR_SZ);
if (n == FSYS_SECTOR_SZ) {
// Boot record read... clear it out
for (int i = 0; i < 0x0DA; i++) {
buffer[i] = 0;
}
// Try to write it back
n = sys_bdev_write(device, 0, buffer, FSYS_SECTOR_SZ);
if (n == FSYS_SECTOR_SZ) {
// Success!
result = 0;
} else {
result = DEV_CANNOT_WRITE;
}
} else {
result = DEV_CANNOT_READ;
}
} else {
result = ERR_OUT_OF_MEMORY;
}
// Clear up the memory we grabbed...
if (buffer) {
free(buffer);
}
return result;
}
const unsigned char boot_from_file_sector[] = {
0x60, 0x00, 0x00, 0x06, // bra.w boot
CPU_M68000, 0x00, 0xf0, 0xe1, // dc.b CPU_M68000, 0, 0xf0, 0xe1
0x30, 0x3c, 0x00, 0x40, // boot: move.w #$40,d0
0x20, 0x7a, 0x00, 0x0c, // move.l path(pc),a0
0x42, 0x82, // clr.l d2
0x42, 0x43, // clr.l d3
0x4e, 0x4f, // trap #15
0x4e, 0x71, // bootloop nop
0x60, 0xfc // bra bootloop
};
/**
* Make the indicated drive booting from a file
*
* @param device the number of the block device to use for booting (-1 to go straight to CLI)
* @param path the path to the file to boot from
* @return 0 on success, any other number is an error
*/
short boot_set_file(short device, const char * path) {
unsigned char * buffer, x;
short result = 0, i = 0;
print(0, "Attempting to boot_set_file\n");
buffer = (unsigned char *)malloc(FSYS_SECTOR_SZ);
if (buffer != 0) {
// Try to read the current sector
short n = sys_bdev_read(device, 0, buffer, FSYS_SECTOR_SZ);
if (n == FSYS_SECTOR_SZ) {
int sector_len = sizeof(boot_from_file_sector);
int path_len = strlen(path);
// Boot record read... clear it out
print(0, "Clearing\n");
for (i = 0; i < 0x1B0; i++) {
buffer[i] = 0;
}
// Copy the boot code over
print(0, "Copying code\n");
for (i = 0; i < sector_len; i++) {
buffer[i] = boot_from_file_sector[i];
}
// Insert the path
for (i = 0; i < path_len; i++) {
buffer[i + sector_len] = path[i];
}
buffer[path_len + sector_len] = 0;
// Try to write it back
print(0, "Writing\n");
n = sys_bdev_write(device, 0, buffer, FSYS_SECTOR_SZ);
if (n == FSYS_SECTOR_SZ) {
// Success!
print(0, "Done\n");
result = 0;
} else {
result = DEV_CANNOT_WRITE;
}
} else {
result = DEV_CANNOT_READ;
}
} else {
result = ERR_OUT_OF_MEMORY;
}
// Clear up the memory we grabbed...
if (buffer) {
free(buffer);
}
return result;
}

View file

@ -38,4 +38,21 @@ extern short boot_screen();
*/
extern void boot_from_bdev(short device);
/**
* Make the indicated drive non booting by erasing the boot information
*
* @param device the number of the block device to use for booting (-1 to go straight to CLI)
* @return 0 on success, any other number is an error
*/
extern short boot_non_booting(short device);
/**
* Make the indicated drive booting from a file
*
* @param device the number of the block device to use for booting (-1 to go straight to CLI)
* @param path the path to the file to boot from
* @return 0 on success, any other number is an error
*/
extern short boot_set_file(short device, const char * path);
#endif

View file

@ -70,6 +70,7 @@ const t_cli_command g_cli_commands[] = {
{ "GETTICKS", "GETTICKS : print number of ticks since reset", cmd_get_ticks },
{ "LABEL", "LABEL <drive#> <label> : set the label of a drive", cmd_label },
{ "LOAD", "LOAD <path> : load a file into memory", cmd_load },
{ "MKBOOT", "MKBOOT <drive #> -r | -b <boot sector path> | -s <start file path> : make a drive bootable", cmd_mkboot },
{ "MKDIR", "MKDIR <path> : create a directory", cmd_mkdir },
{ "PEEK8", "PEEK8 <addr> : print the byte at the address in memory", mem_cmd_peek8 },
{ "PEEK16", "PEEK16 <addr> : print the 16-bit word at the address in memory", mem_cmd_peek16 },
@ -322,7 +323,7 @@ short cli_repl(short channel) {
* @param path the path to the configuration file to load
* @return 0 on success, any other number is an error
*/
extern short cli_exec_batch(short channel, const char * path) {
short cli_exec_batch(short channel, const char * path) {
char command_line[MAX_COMMAND_SIZE];
short fd = sys_fsys_open(path, 0x01); // Open for reading...
@ -336,7 +337,7 @@ extern short cli_exec_batch(short channel, const char * path) {
result = sys_chan_readline(fd, command_line, MAX_COMMAND_SIZE);
if (result > 0) {
// We got a line, so parse it
cli_process_line(channel, command_line)
cli_process_line(channel, command_line);
}
} while (result > 0); // Until we don't get a line

View file

@ -8,6 +8,7 @@
#include "simpleio.h"
#include "cli.h"
#include "proc.h"
#include "boot.h"
#include "cli/dos_cmds.h"
#include "dev/block.h"
#include "dev/fsys.h"
@ -158,7 +159,7 @@ short cmd_copy(short screen, int argc, const char * argv[]) {
char path[MAX_PATH_LEN];
bool is_directory = false;
bool is_append_file = false;
bool is_append_file = false;
TRACE("cmd_copy");
@ -170,7 +171,7 @@ short cmd_copy(short screen, int argc, const char * argv[]) {
is_directory = dst_info.fattrib & AM_DIR;
} else if (result == FR_NO_FILE) {
is_directory = false;
} else {
} else {
goto error;
}
@ -181,7 +182,7 @@ short cmd_copy(short screen, int argc, const char * argv[]) {
result = f_open(&src_file, src_info.fname, FA_READ);
if (result != FR_OK) goto error;
if (is_directory) {
sprintf(path, "%s/%s", dst_info.fname, src_info.fname);
result = f_open(&dst_file, path, FA_WRITE | FA_CREATE_ALWAYS);
@ -190,7 +191,7 @@ short cmd_copy(short screen, int argc, const char * argv[]) {
} else {
result = f_open(&dst_file, path, FA_WRITE | FA_CREATE_ALWAYS);
}
if (result != FR_OK) goto error;
if (result != FR_OK) goto error;
print(screen, (is_append_file) ? "Appending " : "Copying ");
print(screen, src_info.fname);
@ -205,7 +206,7 @@ short cmd_copy(short screen, int argc, const char * argv[]) {
result = f_write(&dst_file, buffer, br, &bw); /* Write it to the destination file */
if (bw < br) break; /* error or disk full */
}
f_close(&src_file);
f_close(&dst_file);
@ -428,6 +429,87 @@ short cmd_label(short screen, int argc, const char * argv[]) {
}
}
/**
* Command to make a device bootable by writing to the MBR or VBR
*
* MKBOOT <drive #> -r --- removes boot record
* MKBOOT <drive #> -b <boot record path> --- installs boot record
* MKBOOT <drive #> -s <start file path> --- defines a startup file
*/
short cmd_mkboot(short screen, int argc, const char * argv[]) {
const char * usage = "USAGE: MKBOOT <drive #> -r\n MKBOOT <drive #> -b <boot record path>\n MKBOOT <drive #> -s <start file path>\n";
short mode = 0;
unsigned char * boot_sector = 0;
unsigned char * new_boot_sector = 0;
char message[80];
short dev = 0;
short i = 0;
short result = 0;
// Parse the inputs...
if (argc == 3) {
// Must be -r
if (strcmp("-r", argv[2]) == 0) {
mode = 0;
dev = cli_eval_number(argv[1]);
} else {
print(screen, usage);
return -1;
}
} else if (argc == 4) {
// Can be either -b or -s
if (strcmp("-b", argv[2]) == 0) {
// -b
mode = 1;
} else if (strcmp("-s", argv[2]) == 0) {
// -s
mode = 2;
} else {
print(screen, usage);
return -1;
}
} else {
// Bad arguments...
print(screen, usage);
return -1;
}
switch (mode) {
case 0:
// Clear out the boot record
result = boot_non_booting(dev);
if (result != 0) {
sprintf(message, "Could not change boot record: %s\n", err_message(result));
print(screen, message);
} else {
print(screen, "Boot record updated.\n");
}
break;
case 2:
// Write a boot sector that loads and runs a file
result = boot_set_file(dev, argv[3]);
if (result != 0) {
sprintf(message, "Could not change boot record: %s\n", err_message(result));
print(screen, message);
} else {
print(screen, "Boot record updated.\n");
}
break;
default:
print(screen, "Unknown MKBOOT operation.\n");
result = -1;
break;
}
return result;
}
/*
* Format a drive
*

View file

@ -84,4 +84,13 @@ extern short cmd_label(short screen, int argc, const char * argv[]);
*/
extern short cmd_format(short screen, int argc, const char * argv[]);
/**
* Command to make a device bootable by writing to the MBR or VBR
*
* MKBOOT <drive #> -r --- removes boot record
* MKBOOT <drive #> -b <boot record path> --- installs boot record
* MKBOOT <drive #> -s <start file path> --- defines a startup file
*/
extern short cmd_mkboot(short screen, int argc, const char * argv[]);
#endif

View file

@ -5,9 +5,9 @@
#ifndef __FSYS_H
#define __FSYS_H
#include "constants.h"
#include "types.h"
#define MAX_PATH_LEN 256
#define DEFAULT_CHUNK_SIZE 256
/**

File diff suppressed because it is too large Load diff

View file

@ -10,7 +10,9 @@
* Miscellaneous definitions
*/
#define MAX_TRIES_BUSY 100000 /* The maximum number of times to check for an operation to complete (general purpose) */
#define FSYS_SECTOR_SZ 512 /* Size of a sector */
#define MAX_PATH_LEN 256 /* Maximum length of a file path */
#define MAX_TRIES_BUSY 100000 /* The maximum number of times to check for an operation to complete (general purpose) */
/*
* Definitions of special characters

18215
src/mapfile

File diff suppressed because it is too large Load diff