]> cloudbase.mooo.com Git - z180-stamp.git/blobdiff - avr/cmd_boot.c
New command: cfboot - boot from cf card.
[z180-stamp.git] / avr / cmd_boot.c
index 73f2cf3e19c1999027e7fda1c6eb222e6952fb3c..b00d0628f9077c01c7acf54ea1d6deb416117904 100644 (file)
@@ -20,6 +20,7 @@
 #include "cli.h"                       /* run_command() */
 #include "env.h"
 #include "con-utils.h"
+#include "getopt-min.h"
 #include "z80-if.h"
 #include "z180-serv.h" /* restart_z180_serv() */
 #include "debug.h"
 /* ugly hack to get Z180 loadfile into flash memory */
 #define const const FLASH
 #include "../z180/hdrom.h"
+#include "../z180/cfboot.h"
 #undef const
 
 
 
-static void z80_load_mem(void)
+static void z80_load_mem(int_fast8_t verbosity,
+                               const FLASH unsigned char data[],
+                               const FLASH unsigned long *sections,
+                               const FLASH unsigned long address[],
+                               const FLASH unsigned long length_of_sections[])
 {
-       unsigned sec = 0;
-       uint32_t sec_base = hdrom_start;
-
-       printf_P(PSTR("Loading Z180 memory... \n"));
-
-       while (sec < hdrom_sections) {
-               printf_P(PSTR("   From: 0x%.5lX to: 0x%.5lX    (%5li bytes)\n"),
-                               hdrom_address[sec],
-                               hdrom_address[sec]+hdrom_length_of_sections[sec] - 1,
-                               hdrom_length_of_sections[sec]);
-
-               z80_write_block_P((const FLASH unsigned char *) &hdrom[sec_base],  /* src */
-                               hdrom_address[sec],                  /* dest */
-                               hdrom_length_of_sections[sec]);      /* len */
-               sec_base+=hdrom_length_of_sections[sec];
-               sec++;
+       uint32_t sec_base = 0;
+
+       if (verbosity > 1)
+               printf_P(PSTR("Loading Z180 memory... \n"));
+
+       for (unsigned sec = 0; sec < *sections; sec++) {
+               if (verbosity > 0) {
+                       printf_P(PSTR("   From: 0x%.5lX to: 0x%.5lX    (%5li bytes)\n"),
+                                       address[sec],
+                                       address[sec]+length_of_sections[sec] - 1,
+                                       length_of_sections[sec]);
+               }
+
+               z80_write_block_P((const FLASH unsigned char *) &data[sec_base],  /* src */
+                               address[sec],                  /* dest */
+                               length_of_sections[sec]);      /* len */
+               sec_base += length_of_sections[sec];
        }
 }
 
@@ -64,13 +71,206 @@ command_ret_t do_loadf(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]
                my_puts_P(PSTR("Bus timeout\n"));
                return  CMD_RET_FAILURE;
        }
-       z80_load_mem();
+       z80_load_mem(2, hdrom,
+                               &hdrom_sections,
+                               hdrom_address,
+                               hdrom_length_of_sections);
+
        z80_bus_cmd(Release);
 
        return CMD_RET_SUCCESS;
 }
 
 
+void print_vars(char *title)
+{
+       uint8_t buf[5];
+       zstate_t state = z80_bus_state();
+
+       if((state & ZST_ACQUIRED) == 0)
+               z80_bus_cmd(Request);
+
+       z80_read_block(buf,     9, sizeof buf);
+
+       if((state & ZST_ACQUIRED) == 0)
+               z80_bus_cmd(Release);
+
+       printf_P(PSTR("%s: stage: %d, flag: 0x%.02x, result: %d, IDE stat/error: 0x%.02x/0x%.02x\n"),
+                               title, buf[0], buf[1], buf[2], buf[3], buf[4]);
+}
+
+
+/*
+ *  bootcf [options]
+ *
+ *             -a      address                 (100h)
+ *             -s      start sector    (0)
+ *             -c      sector count    (7)
+ *             -i      Partition id    (52)
+ *             -n  load only
+ *             -t      timeout                 (10000)
+ *             -v      verbose
+ */
+
+command_ret_t do_bootcf(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+       struct {
+               uint8_t  jr[2];
+               uint16_t loadaddr;
+               uint8_t  sec_start;
+               uint8_t  sec_cnt;
+               uint8_t  part_id;
+               uint16_t timeout;
+               uint8_t  stop_stage;
+       } boot_param;
+
+       struct {
+               uint8_t  stop_stage;
+               uint8_t  done;
+               uint8_t  result;
+               uint8_t  ide_stat;
+               uint8_t  ide_error;
+       } boot_res;
+
+       int_fast8_t verbosity = 0;
+       uint8_t stages;
+       uint32_t val;
+
+       (void) cmdtp; (void) flag;
+
+       /* get default values */
+       memcpy_P(&boot_param, cfboot, sizeof boot_param);
+       stages = boot_param.stop_stage;
+
+       /* reset getopt() */
+       optind = 0;
+
+       int opt;
+       while ((opt = getopt(argc, argv, PSTR("vna:s:c:t:i:"))) != -1) {
+               switch (opt) {
+               case 'v':
+                       verbosity++;
+                       break;
+               case 'n':
+                       if (boot_param.stop_stage > 0)
+                               boot_param.stop_stage--;
+                       break;
+               case 'a':
+                       val = strtoul(optarg, NULL, 16);
+                       if (val < 0x100 || val > 0xFE00) {
+                               printf_P(PSTR("Address out of range: 0x%.4lX\n"), val);
+                               return CMD_RET_FAILURE;
+                       }
+                       boot_param.loadaddr = val;
+                       break;
+               case 's':
+                       val = strtoul(optarg, NULL, 16);
+                       if (val > 255) {
+                               printf_P(PSTR("Start sector out of range: 0x%lX\n"), val);
+                               return CMD_RET_FAILURE;
+                       }
+                       boot_param.sec_start = val;
+                       break;
+               case 'c':
+                       val = strtoul(optarg, NULL, 16);
+                       if (val > 127) {
+                               printf_P(PSTR("Sector count out of range: 0x%lX\n"), val);
+                               return CMD_RET_FAILURE;
+                       }
+                       boot_param.sec_cnt = val;
+                       break;
+               case 't':
+                       val = strtoul(optarg, NULL, 10);
+                       if (val < 0x1 || val > 0xFFFF) {
+                               printf_P(PSTR("Timeout value out of range: 0x%lX\n"), val);
+                               return CMD_RET_FAILURE;
+                       }
+                       boot_param.loadaddr = val;
+                       break;
+               case 'i':
+                       val = strtoul(optarg, NULL, 16);
+                       if (val < 0x01 || val > 0xFF) {
+                               printf_P(PSTR("Partition id out of range: 0x%lX\n"), val);
+                               return CMD_RET_FAILURE;
+                       }
+                       boot_param.part_id = val;
+                       break;
+               default: /* '?' */
+                       return CMD_RET_USAGE;
+               }
+       }
+
+       /* remaining arguments */
+       argc -= optind;
+       if (argc) {
+               my_puts_P(PSTR("Argument error!\n"));
+               return CMD_RET_USAGE;
+       }
+
+       if ((val = (uint32_t) boot_param.loadaddr + boot_param.sec_cnt * 512) >= 0xFF00) {
+               printf_P(PSTR("Top address out of range: 0x%.4lX\n"), val);
+               return CMD_RET_FAILURE;
+       }
+
+
+
+       if (z80_bus_state() & ZST_RUNNING) {
+               my_puts_P(PSTR("CPU is allready running!\n"));
+               return CMD_RET_FAILURE;
+       }
+       if (!(z80_bus_cmd(Request) & ZST_ACQUIRED)) {
+               my_puts_P(PSTR("Bus timeout\n"));
+               return  CMD_RET_FAILURE;
+       }
+       z80_load_mem(verbosity, cfboot,
+                               &cfboot_sections,
+                               cfboot_address,
+                               cfboot_length_of_sections);
+
+       z80_write_block((const uint8_t *) &boot_param,
+                               cfboot_address[0], sizeof boot_param);
+       z80_bus_cmd(Release);
+
+       if (boot_param.stop_stage == 0) {
+               printf_P(PSTR("Bootloader loaded at: 0x%.4X\n"), (uint16_t) cfboot_address[0]);
+       } else {
+               printf_P(PSTR("Executing %d of %d Bootloader stages...\n"),
+                               boot_param.stop_stage, stages);
+
+               z80_bus_cmd(Run);
+               z80_bus_cmd(Release);
+
+               clear_ctrlc();          /* forget any previous Control C */
+               for (boot_res.done = 0; boot_res.done != 0xFF;) {
+                       _delay_ms(8);
+                       /* check for ctrl-c to abort... */
+                       if (had_ctrlc() || ctrlc()) {
+                               break;
+                       }
+                       z80_bus_cmd(Request);
+                       z80_read_block((uint8_t *) &boot_res,
+                                       cfboot_address[0]+sizeof boot_param - 1, sizeof boot_res);
+                       z80_bus_cmd(Release);
+               }
+
+               if (boot_res.done != 0xFF) {
+                       z80_bus_cmd(Reset);
+                       my_puts_P(PSTR("Abort\n"));
+               } else {
+                       if (boot_param.stop_stage == stages) {
+                               my_puts_P(PSTR("Booting...\n"));
+                       } else {
+                               z80_bus_cmd(Reset);
+                               printf_P(PSTR("Bootloader stopped at stage %d, result: %d, IDE stat/error: 0x%.02x/0x%.02x\n"),
+                                       boot_param.stop_stage - boot_res.stop_stage,
+                                       boot_res.result, boot_res.ide_stat, boot_res.ide_error);
+                       }
+               }
+       }
+
+       return CMD_RET_SUCCESS;
+}
+
 command_ret_t do_busreq_pulse(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
        uint16_t count=1;