diff --git a/.gitignore b/.gitignore index c6127b3..fd888cc 100644 --- a/.gitignore +++ b/.gitignore @@ -50,3 +50,4 @@ modules.order Module.symvers Mkfile.old dkms.conf +.vscode/settings.json diff --git a/progheader.md b/progheader.md index 5100240..219402c 100644 --- a/progheader.md +++ b/progheader.md @@ -6,9 +6,7 @@ To recognize a program or bootable module in RAM or flash, the toolbox needs a s | ---- | ----- | | 0 | Signature: $F8 | | 1 | Signature: $16 | -| 2 | Size of the program in 8KB blocks | -| 3 | Reserved | -| 4 -- 5 | Starting address of the program, little-endian format | +| 2 -- 5 | Starting address of the program, little-endian format | | 6 | Header structure version number | | 7 -- 9 | Reserved | | 10 -- m | Zero-terminated string: name of the program | diff --git a/src/C256/flash-u-plus.scm b/src/C256/flash-u-plus.scm index c66e27b..5aa41a2 100644 --- a/src/C256/flash-u-plus.scm +++ b/src/C256/flash-u-plus.scm @@ -9,13 +9,13 @@ (section (registers ztiny))) (memory LoRAM (address (#x00c100 . #x00efff)) (section stack data zdata data heap)) - (memory NearRAM1 (address (#x010000 . #x017fff)) + (memory NearRAM1 (address (#x350000 . #x357fff)) (section znear near)) - (memory NearRAM2 (address (#x018000 . #x01ffff)) + (memory NearRAM2 (address (#x358000 . #x35ffff)) (section cnear)) - (memory FarRAM1 (address (#x020000 . #x02ffff)) + (memory FarRAM1 (address (#x360000 . #x36ffff)) (section far huge)) - (memory FarRAM2 (address (#x030000 . #x03ffff)) + (memory FarRAM2 (address (#x370000 . #x37ffff)) (section zfar zhuge )) (memory LoCode (address (#x00f000 . #x00ffdf)) (scatter-to LoCodeStorage) (section code cdata (jumptable #x00f000))) diff --git a/src/Makefile b/src/Makefile index 343eb39..51fb672 100644 --- a/src/Makefile +++ b/src/Makefile @@ -56,7 +56,7 @@ else LDFLAGS=$(LDFLAGS_FOR_UNIT) --list-file toolbox.map endif -SRCS = toolbox.c log.c memory.c proc.c ring_buffer.c simpleio.c sys_general.c utilities.c $(SRCS_FOR_UNIT) # $(C_SRCS_DEBUGGER) +SRCS = toolbox.c log.c boot.c memory.c proc.c ring_buffer.c simpleio.c sys_general.c utilities.c $(SRCS_FOR_UNIT) # $(C_SRCS_DEBUGGER) OBJS = $(patsubst %.s,%.o,$(patsubst %.c,%.o,$(SRCS))) OBJS4RM = $(subst /,\\,$(OBJS)) LIBS = dev/devices.a snd/sound.a fatfs/fatfs.a @@ -88,7 +88,7 @@ fatfs/fatfs.a: # Clean up after a build clean: - $(RM) $(OBJS4RM) toolbox.s37 *.lst *.map + $(RM) $(OBJS4RM) toolbox.s37 *.lst *.map *.raw $(MAKE) --directory=dev clean $(MAKE) --directory=snd clean $(MAKE) --directory=fatfs clean \ No newline at end of file diff --git a/src/boot.c b/src/boot.c index 82d1b61..c994069 100644 --- a/src/boot.c +++ b/src/boot.c @@ -1,629 +1,135 @@ /** * @file boot.c - * - * Routines to support the boot process + * @author your name (you@domain.com) + * @brief Boot sequence control code for managing loading up the user's control code + * @version 0.1 + * @date 2024-06-09 + * + * @copyright Copyright (c) 2024 + * */ -#include "log_level.h" -#ifndef DEFAULT_LOG_LEVEL - #define DEFAULT_LOG_LEVEL LOG_TRACE -#endif - -#include -#include -#include -#include "sys_general.h" #include "boot.h" -#include "constants.h" -#include "errors.h" -#include "gabe_reg.h" -#include "log.h" -#include "simpleio.h" -#include "syscalls.h" -#include "vicky_general.h" -#include "cli/cli.h" -#include "dev/kbd_mo.h" -#include "dev/txt_screen.h" +#include "memory.h" +#include "proc.h" -#include "rsrc/font/quadrotextFONT.h" -#if MODEL == MODEL_FOENIX_A2560U || MODEL == MODEL_FOENIX_A2560U_PLUS -#include "rsrc/bitmaps/splash_a2560u.h" -#include "dev/txt_a2560u.h" -#elif MODEL == MODEL_FOENIX_A2560K -#include "rsrc/bitmaps/splash_a2560k.h" -#elif MODEL == MODEL_FOENIX_A2560X || MODEL == MODEL_FOENIX_GENX -#include "rsrc/bitmaps/splash_a2560x.h" -#endif +#include -#if MODEL == MODEL_FOENIX_A2560K - #define SPLASH_WAIT_SEC 10 /* How many seconds to wait on the splash screen */ -#else - #define SPLASH_WAIT_SEC 4 /* How many seconds to wait on the splash screen */ -#endif -/* - * Important scan codes - */ -#define SC_F1 0x3B -#define SC_F2 0x3C -#define SC_F3 0x3D -#define SC_SPACE 0x39 -#define SC_RETURN 0x1C +const uint32_t boot_record_alignment = 8192; // Number of bytes for boot record alignement +const uint32_t boot_firmware_address = 0x380000; -/* TODO: move this to constants.h */ - - -#define BOOT_SECTOR_BUFFER ((unsigned char *)0x00004000) -#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 */ - -#define FDC_VBR_JUMP 0x000 // Intel 80x86 machine language jump... 3 bytes -#define FDC_VBR_OEMNAME 0x003 // OEM Name... 8 bytes -#define FDC_VBR_BPB 0x00B // BIOS Parameter Block -#define FDC_VBR_BYTES_PER_SECTOR 0x00B // Number of bytes per sector... 2 bytes -#define FDC_VBR_SECTORS_PER_CLUSTER 0x00D // Number of sectors per cluster... 1 byte -#define FDC_VBR_RESERVED_SECTORS 0x00E // Number of reserved sectors... 2 bytes -#define FDC_VBR_FAT_COUNT 0x010 // Number of file allocation tables... 1 byte -#define FDC_VBR_MAX_ROOT_ENTRIES 0x011 // Maximum number of root directory entries... 2 bytes -#define FDC_VBR_SECTORS 0x013 // Number of logical sectors in FAT12/16... 2 bytes -#define FDC_VBR_MEDIA_TYPE 0x015 // Media type code... 1 byte -#define FDC_VBR_SECTORS_PER_FAT 0x016 // Number of sectors per file allocation table... 2 bytes -#define FDC_VBR_SECTORS_PER_TRACK 0x018 // Number of sectors per track... 2 bytes -#define FDC_VBR_HEADS 0x01A // Number of heads... 2 bytes -#define FDC_VBR_HIDDEN_SECTORS 0x01C // Number of hidden sectors... 2 bytes -#define FDC_VBR_TOTAL_SECTORS 0x01E // Total number of sectors... 2 bytes -#define FDC_VBR_BOOT_CODE 0x060 // Start of boot sector code - -#define BOOT_CODE_VBR_OFF FDC_VBR_BOOT_CODE /* Offset to the code in the VBR for floppy drives */ -#define BOOT_CPUID_VBR_OFF BOOT_CODE_VBR_OFF+4 /* Offset to the CPUID in the VBR for floppy drives */ -#define BOOT_SIG_VBR_OFF BOOT_CODE_VBR_OFF+6 /* Offset to the boot signature in the VBR for floppy drives */ - -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 */ -const char * MCP_INIT_HDC = "/hd/system/mcp.init"; /**< Path to config file on the IDE drive */ - -// Colors for the A2560K keyboard LED matrix -const unsigned short kbd_colors[] = {0x000F, 0x0FF, 0x00F0, 0x0FF0, 0x0F70, 0x0F00}; - -/** - * On the A2560K, animate the LEDs based on the current time while we're waiting for a key press - * - * @param max_ticks the value of the jiffy counter when the boot screen will end - * @param ticks the current value of the jiffy counter - * @param min_ticks the starting value of the jiffy counter - */ -void boot_animate_keyboard(unsigned long max_ticks, unsigned long ticks, unsigned long min_ticks) { -#if MODEL == MODEL_FOENIX_A2560K - const int animation_steps = 7; - int current_step = (int)(((ticks - min_ticks) * animation_steps) / (max_ticks - min_ticks)); - int i; - - for (i = 0; i < current_step; i++) { - kbdmo_set_led_matrix_row(current_step - i - 1, kbd_colors[5 - i]); - } -#endif -} - -/** - * Determine if a sector loaded from a device is bootable - * - * @param sector pointer to where the sector is stored in memory - * @param device the number of the block device - * - * @return 0 if not bootable, non-zero if bootable - */ -bool is_bootable(unsigned char * sector, short device) { - switch(device) { - case BDEV_FDC: - // The SDC and HDC boot off the MBR... - // Check for the CPUID and boot signature - if ((sector[BOOT_CPUID_VBR_OFF] == CPU_M68000) || - (sector[BOOT_CPUID_VBR_OFF] == CPU_M68040)) { - if ((sector[BOOT_SIG_VBR_OFF] == ((BOOT_SIG >> 8) & 0x00FF)) && - (sector[BOOT_SIG_VBR_OFF+1] == (BOOT_SIG & 0x00FF))) { - // The CPU is supported, and the boot signature is correct - return true; - } - } - 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 true; - } - } - break; - - default: - // Otherwise: we're not bootable - break; - } - - // If we have reached this point, the sector is not bootable - return false; -} - -/** - * Run the code in the boot sector - * - * @param device the number of the block device for the sector - */ -void boot_sector_run(short device) { - FUNC_V_2_V boot_sector = 0; - - switch(device) { - case BDEV_FDC: - // The FDC boots off the Volume Boot Record (offset 0x060) - boot_sector = (FUNC_V_2_V)(BOOT_SECTOR_BUFFER + BOOT_CODE_VBR_OFF); - boot_sector(); - break; - - case BDEV_SDC: - case BDEV_HDC: - // The SDC and HDC both boot off the MBR - boot_sector = (FUNC_V_2_V)(BOOT_SECTOR_BUFFER); - boot_sector(); - break; - - default: - break; - } -} - -void make_key_name(const char * original, char * buffer) { - int x; - for (x = 0; x < strlen(original); x++) { - buffer[x] = 0x80 | original[x]; - } - buffer[strlen(original)] = 0; -} - -/* - * Load and display the boot splash screen on the graphics screen - * - * @return boot device selected by user - */ -short boot_screen() { - t_rect region; - short device = BOOT_DEFAULT; - short screen; - char buffer[256]; - char entry[50]; - unsigned long target_jiffies = 0; - unsigned long min_jiffies = 0; - unsigned long current_jiffies = 0; - int i = 0; - const unsigned char * pixels; - volatile unsigned char * vram = VRAM_Bank0; - t_sys_info info; - char f1[3], f2[3], f3[3]; - char space[10], cr_text[10]; - - TRACE("boot_screen"); - - // We'll display boot information on the common screen - screen = 0; - - /* Turn off the screen */ - txt_set_mode(screen, 0); - - for (i = 0; i < 256; i++) { - LUT_0[4*i] = splashscreen_lut[4*i]; - LUT_0[4*i+1] = splashscreen_lut[4*i+1]; - LUT_0[4*i+2] = splashscreen_lut[4*i+2]; - LUT_0[4*i+3] = splashscreen_lut[4*i+3]; - } - -#if 1 - /* Copy the bitmap to video RAM, it has simple RLE compression */ - for (pixels = splashscreen_pix; *pixels != 0;) { - unsigned char count = *pixels++; - unsigned char pixel = *pixels++; - for (i = 0; i < count; i++) { - *vram++ = pixel; - } - } -#else - #if 0 - // For debug, try something more basic - const line_len = 640; - //memset(vram, 1, 640*480); - for (i=0; i < 640*480; i++) - vram[i] = 3; - for (i = 0; i < 480; i++) - vram[640*i + i] = 2; - #endif -#endif - /* Set up the bitmap */ - *BM0_Addy_Pointer_Reg = 0; /* Start of VRAM */ - *BM0_Control_Reg = 1; - - /* Set a background color for the bitmap mode */ -#if HAS_DUAL_SCREEN - *BackGroundControlReg_B = 0x00202020; - screen = 0; -#else - *BackGroundControlReg_A = 0x00402040; - screen = 0; -#endif - - /* Display the splashscreen at 640x480 without a border */ - txt_set_resolution(screen, 640, 480); - txt_set_border(screen, 0, 0); - txt_set_font(screen, 8, 8, quadrotextFONT); - - region.origin.x = 0; - region.origin.y = 0; - region.size.width = 0; - region.size.height = 0; - txt_set_region(screen, ®ion); - txt_setsizes(screen); - txt_set_mode(screen, TXT_MODE_TEXT | TXT_MODE_BITMAP); - - /* Disable the cursor, set the color, clear the text screen, and display the text message */ - txt_set_cursor(screen, 0, 0, 0); // Disable the cursor - txt_set_color(screen, 15, 0); // White on transparent - txt_fill(screen, ' '); // Clear the screen - - make_key_name("F1", f1); - make_key_name("F2", f2); - make_key_name("F3", f3); - make_key_name("SPACE", space); - make_key_name("RETURN", cr_text); - -#if HAS_FLOPPY - sprintf(buffer, "BOOT: %s=SD CARD, %s=HARD DRIVE, s=FLOPPY, %s=DEFAULT, %s=SAFE", f1, f2, f3, space, cr_text); -#else - sprintf(buffer, "BOOT: %s=SD CARD, %s=HARD DRIVE, %s=DEFAULT, %s=SAFE", f1, f2, space, cr_text); -#endif - txt_set_xy(screen, (80 - strlen(buffer)) / 2, 58); - sys_chan_write(screen, buffer, strlen(buffer)); - - // Get the information about the system - sys_get_info(&info); - - region.origin.x = 49; - region.origin.y = 1; - region.size.width = 40; - region.size.height = 20; - txt_set_region(screen, ®ion); - - sprintf(buffer, "\x1b[HFOENIX/MCP V: %02u.%04u.%04u\n", info.mcp_version, info.mcp_rev, info.mcp_build); - print(screen, buffer); - str_upcase(info.model_name, entry); - sprintf(buffer, " MODEL: %s\n", entry); - print(screen, buffer); - str_upcase(info.cpu_name, entry); - sprintf(buffer, " CPU: %s\n", entry); - print(screen, buffer); - sprintf(buffer, " CLOCK (KHZ): %u\n", info.cpu_clock_khz); - print(screen, buffer); - sprintf(buffer, " FPGA V: %u.%02u.%04u\n", (unsigned int)info.fpga_model, info.fpga_version, info.fpga_subver); - print(screen, buffer); - - /* Wait until the target duration has been reached _or_ the user presses a key */ - sprintf(buffer, "Booting from default device...\n"); - min_jiffies = sys_time_jiffies(); - target_jiffies = min_jiffies + SPLASH_WAIT_SEC * 60; - - while (target_jiffies > (current_jiffies = sys_time_jiffies())) { - boot_animate_keyboard(target_jiffies, current_jiffies, min_jiffies); - - unsigned short scan_code = sys_kbd_scancode(); - if (scan_code == 0) - continue; - - switch (scan_code) { - case SC_F1: - device = BDEV_SDC; - strcpy(buffer, "Booting from SD card.\n"); - break; - - case SC_F2: - device = BDEV_HDC; - strcpy(buffer, "Booting from hard drive.\n"); - break; - -#if HAS_FLOPPY - case SC_F3: - device = BDEV_FDC; - strcpy(buffer, "Booting from floppy drive.\n"); - break; -#endif - - case SC_RETURN: - device = BOOT_SAFE; - strcpy(buffer, "Booting directly to the command line.\n"); - break; - - default: - device = BOOT_DEFAULT; - break; - } - break; - } - - /* Initialise all screens */ - txt_init_screen(screen); /* This is the one used for the boot message */ - /* No need to txt_set_resolution(screen, 0, 0) because during screen_init, the defaults are applied */ -#if MODEL == MODEL_FOENIX_A2560K || MODEL == MODEL_FOENIX_A2560X || MODEL == MODEL_FOENIX_GENX - txt_set_resolution(1, 0, 0); // Set the resolution based on the DIP switch -#endif - print(screen, buffer); - -#if MODEL == MODEL_FOENIX_A2560K - // Turn off the keyboard LEDs - kbdmo_set_led_matrix_fill(0); -#endif - - return device; -} - -/** - * Start the boot process after initializing the MCP - * - * @param device the number of the block device to use for booting (-1 to go straight to CLI) - */ -void boot_from_bdev(short device) { - char initial_path[10]; -#if MODEL == MODEL_FOENIX_A2560K - unsigned int boot_dip = 0; // The setting on the user and boot mode DIP switches -#elif MODEL == MODEL_FOENIX_GENX || MODEL == MODEL_FOENIX_A2560X || MODEL_FOENIX_A2560U_PLUS - unsigned short boot_dip = 0; // The setting on the user and boot mode DIP switches -#endif - short bootable = 0; // Is the boot sector of the selected device bootable? - - TRACE1("boot_from_bdev(%d)", device); - - initial_path[0] = '\0'; - - // Get the boot device - switch (device) { - case BOOT_DEFAULT: - // User chose the default. Look at the DIP switches to determine the boot source - boot_dip = *GABE_DIP_REG & GABE_DIP_BOOT_MASK; - switch (boot_dip) { - case 0x0000: - // Boot from IDE - device = BDEV_HDC; - log(LOG_INFO, "Boot DIP set for IDE"); - strcpy(initial_path, "/hd"); - break; - - case 0x0001: - // Boot from SDC - device = BDEV_SDC; - log(LOG_INFO, "Boot DIP set for SDC"); - strcpy(initial_path, "/sd"); - break; - -#if HAS_FLOPPY - case 0x0002: - // Boot from Floppy - device = BDEV_FDC; - log(LOG_INFO, "Boot DIP set for FDC"); - strcpy(initial_path, "/fd"); - break; -#endif - default: - // Boot straight to REPL - log(LOG_INFO, "Boot DIP set for REPL"); - strcpy(initial_path, "/sd"); - device = -1; - break; - } - break; - - default: - break; - } - - if (device >= 0) { - int i; - - for (i = 0; i < 512; i++) { - // Zero out the buffer - BOOT_SECTOR_BUFFER[i] = 0; - } - - // Try to load the boot sector - DEBUG("boot_from_bdev: trying to read 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) { - DEBUG("boot_from_bdev: boot sector is bootable, trying to run"); - // If bootable, run it - boot_sector_run(device); - - } else { - DEBUG("boot_from_bdev: boot sector not bootable"); - // If not bootable... - - // Get the screen for the CLI - short cli_screen = cli_txt_screen_get(); - - if (device >= 0) { - DEBUG("Execute startup file on boot device (if present)"); - switch (device) { - case BDEV_SDC: - strcpy(initial_path, "/sd"); - if (cli_exec_batch(cli_screen, MCP_INIT_SDC) != 0) { - cli_exec_batch(cli_screen, MCP_INIT_HDC); - } - break; - - case BDEV_FDC: - strcpy(initial_path, "/fd"); - if (cli_exec_batch(cli_screen, MCP_INIT_FDC) != 0) { - cli_exec_batch(cli_screen, MCP_INIT_HDC); - } - break; - - case BDEV_HDC: - strcpy(initial_path, "/hd"); - cli_exec_batch(cli_screen, MCP_INIT_HDC); - break; - - default: - break; - } - } - - // Start up the command shell - cli_start_repl(cli_screen, initial_path); - } -} - -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 - 0x43, 0xfa, 0x00, 0x0e, // lea (path,pc),a1 - 0x22, 0x09, // move.l a1,d1 - 0x42, 0x82, // clr.l d2 - 0x42, 0x83, // clr.l d3 - 0x4e, 0x4f, // trap #15 - 0x4e, 0x71, // bootloop nop - 0x60, 0xfc // bra bootloop +enum boot_src_e { + BOOT_SRC_NONE = 0, // Nothing more to check + BOOT_SRC_RAM, // Check RAM for a bootable + BOOT_SRC_ROM, // Check the ROM drive + BOOT_SRC_CARTRIDGE, // Check the cartridge + BOOT_SRC_SD0, // Check the external SD card + BOOT_SRC_SD1 // Check the internal SD card / IDE }; /** - * 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 + * @brief Structure to hold a boot record + * */ -short boot_non_booting(short device) { - unsigned char * buffer; - short result = 0; +typedef struct boot_record_s { + char signature1; + char signature2; + uint32_t start_address; + uint8_t version; + uint8_t reserved0; + uint8_t reserved1; + uint8_t reserved2; + char * text_data; +} boot_record_t, *boot_record_p; - 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) { - short sector_offset = 0; +/** + * @brief List bootable areas to check, in priority order + * + */ +static enum boot_src_e boot_chain[] = { + BOOT_SRC_RAM, + BOOT_SRC_CARTRIDGE, + BOOT_SRC_SD0, + BOOT_SRC_SD1, + BOOT_SRC_ROM, + BOOT_SRC_NONE +}; - if (device == BDEV_FDC) { - // Point to the beginning of the boot code for the FDC (VBR) - sector_offset = BOOT_CODE_VBR_OFF; +/** + * @brief A holder for empty arguments list so we have something to point to when starting a binary file + * + */ +static char * boot_args[] = { + 0, + 0 +}; - } else { - // Point to the beginning of the boot code for the SDC/HDD (MBR) - sector_offset = BOOT_CODE_MBR_OFF; - } - - // Boot record read... clear out the boot code - for (int i = 0; i < sizeof(boot_from_file_sector); i++) { - buffer[sector_offset + 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; +/** + * @brief Check the memory indicated to validate it is a boot record... if so, launch the code indicated + * + * @param record pointer to the possible boot record + * @return 1 if success, 0 if boot record not validated + */ +short boot_ram_launch(boot_record_p record) { + if ((record->signature1 == 0xf8) && (record->signature2 == 0x16) && (record->version == 0)) { + // Memory does indeed hold a boot record + proc_exec(record->start_address, 0, 0, 0); + return 1; + } else { + return 0; + } } /** - * 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 + * @brief Look for a boot record in RAM + * @return 1 if success, 0 if boot record not validated + * */ -short boot_set_file(short device, const char * path) { - unsigned char * buffer, x; - short result = 0, i = 0; +short boot_ram() { + unsigned long top_ram = mem_get_ramtop(); + for (uint32_t address = 0; address < top_ram; address += boot_record_alignment) { + if (boot_ram_launch((boot_record_p)address)) { + return 1; + } + } - buffer = (unsigned char *)malloc(FSYS_SECTOR_SZ); - if (buffer != 0) { - // Try to read the current sector - bdev_init(device); - 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 sector_offset = 0; - int path_len = strlen(path); - - if (device == BDEV_FDC) { - // Set up the floppy disk boot record - sector_offset = BOOT_CODE_VBR_OFF; - - // Write 80x86 code to infinite loop at the start of the boot sector - // This will help maintain compatibility with MS-DOS and Windows machines - buffer[0] = 0xEB; - buffer[1] = 0xFF; - buffer[2] = 0x90; - - } else { - // Set up the SDC or HDC master boot record - sector_offset = BOOT_CODE_MBR_OFF; - } - - // Copy the boot code over - for (i = 0; i < sector_len; i++) { - buffer[sector_offset + i] = boot_from_file_sector[i]; - } - - // Insert the path - for (i = 0; i < path_len; i++) { - buffer[sector_offset + i + sector_len] = path[i]; - } - buffer[sector_offset + sector_len + path_len] = 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; + return 0; +} + +/** + * @brief Look for a boot record in the flash cartridge + * @return 1 if success, 0 if boot record not validated + * + */ +short boot_cartridge() { + return 0; +} + +/** + * @brief Find and launch the user's code + * + */ +void boot_launch() { + for (short i = 0; boot_chain[i] != BOOT_SRC_NONE; i++) { + switch(boot_chain[i]) { + case BOOT_SRC_RAM: + if (boot_ram()) { + return; + } + break; + + case BOOT_SRC_SD0: + if (proc_run("/sd0/fnxboot.pgz", 0, boot_args) == 0) { + return; + } else if (proc_run("/sd0/fnxboot.pgx", 0, boot_args) == 0) { + return; + } else if (proc_run("/sd0/fnxboot.elf", 0, boot_args) == 0) { + return; + } + break; + + default: + break; + } + } } diff --git a/src/boot.h b/src/boot.h index e978653..e45c4d6 100644 --- a/src/boot.h +++ b/src/boot.h @@ -1,44 +1,23 @@ /** - * @file boot.h - * - * Routines to support the boot process + * @file boot.c + * @author your name (you@domain.com) + * @brief Boot sequence control code for managing loading up the user's control code + * @version 0.1 + * @date 2024-06-09 + * + * @copyright Copyright (c) 2024 + * */ -#ifndef __BOOT_H -#define __BOOT_H +#ifndef __boot_h__ +#define __boot_h__ -#define BOOT_DEFAULT -1 -#define BOOT_SAFE -2 - -/* - * Load and display the boot splash screen on the graphics screen - * - * @return boot device selected by user - */ -extern short boot_screen(); +#include /** - * Start the boot process after initializing the MCP - * - * @param device the number of the block device to use for booting (-1 to go straight to CLI) + * @brief Find and launch the user's code + * */ -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); +extern void boot_launch(); #endif diff --git a/src/toolbox.c b/src/toolbox.c index 62f556c..d39e0d8 100644 --- a/src/toolbox.c +++ b/src/toolbox.c @@ -60,7 +60,7 @@ #include "rsrc/font/MSX_CP437_8x8.h" #include "rsrc/bitmaps/splash_c256_u.h" -const char* VolumeStr[FF_VOLUMES] = { "sd" }; +const char* VolumeStr[FF_VOLUMES] = { "sd0" }; extern unsigned long __memory_start; @@ -244,10 +244,6 @@ void initialize() { } } -#define BOOT_DEFAULT -1 // User chose default, or the time to over-ride has passed - -t_file_info file; - int main(int argc, char * argv[]) { short result; short i; @@ -255,24 +251,9 @@ int main(int argc, char * argv[]) { initialize(); - // // Display the splash screen and wait for user input - // short boot_dev = boot_screen(); - - // // Start the boot process - // boot_from_bdev(boot_dev); - - // log(LOG_INFO, "Stopping."); - - printf("Loading splashscreen...\n"); - - // txt_clear(0, 2); - bm_load_clut(0, splashscreen_lut); - bm_load_rle((uint8_t *)0x010000, splashscreen_pix, 640, 480); - printf("Splash screen rendered\n"); - vdma_copy_linear((uint8_t *)0xb00000, (uint8_t *)0x010000, (long)640 * (long)480); - printf("Splash screen copied to VRAM\n"); - bm_set_data(0, (uint8_t *)0xb00000); - bm_set_visibility(0, 0, 1); + // Attempt to start up the user code + log(LOG_INFO, "Looking for user startup code:"); + boot_launch(); printf("Done.\n");