/*
- * (C) Copyright 2014 Leo C. <erbl259-lmu@yahoo.de>
+ * (C) Copyright 2014-2016 Leo C. <erbl259-lmu@yahoo.de>
*
* (C) Copyright 2000-2003
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
/*
* Misc boot support
*/
-#include "common.h"
-#include <stdlib.h>
+#include "cmd_boot.h"
#include <ctype.h>
#include <util/atomic.h>
-#include "command.h"
-#include "cli_readline.h"
-#include "cli.h"
+#include "cli_readline.h" /* console_buffer[] */
+#include "cli.h" /* run_command() */
#include "env.h"
+#include "eval_arg.h"
#include "con-utils.h"
+#include "getopt-min.h"
#include "z80-if.h"
-#include "z180-serv.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];
}
}
-command_ret_t do_loadf(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+command_ret_t do_loadf(cmd_tbl_t *cmdtp, uint_fast8_t flag, int argc, char * const argv[])
{
(void) cmdtp; (void) flag; (void) argc; (void) 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;
}
-command_ret_t do_busreq_pulse(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+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, uint_fast8_t 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 stages;
+ } boot_param;
+
+ struct {
+ uint8_t stages;
+ uint8_t done;
+ uint8_t result;
+ uint8_t ide_stat;
+ uint8_t ide_error;
+ } boot_res;
+
+ int_fast8_t verbosity = 0;
+ uint8_t default_stages;
+ uint32_t val;
+
+ (void) cmdtp; (void) flag;
+
+ /* get default values */
+ memcpy_P(&boot_param, cfboot, sizeof boot_param);
+ default_stages = boot_param.stages;
+
+ /* 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.stages > 0)
+ boot_param.stages--;
+ break;
+ case 'a':
+ val = eval_arg(optarg, NULL);
+ 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 = eval_arg(optarg, NULL);
+ 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 = eval_arg(optarg, NULL);
+ 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 = eval_arg(optarg, NULL);
+ if (val < 0x1 || val > 0xFFFF) {
+ printf_P(PSTR("Timeout value out of range: 0x%lX\n"), val);
+ return CMD_RET_FAILURE;
+ }
+ boot_param.timeout = val;
+ break;
+ case 'i':
+ val = eval_arg(optarg, NULL);
+ 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.stages == 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.stages, default_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.stages == default_stages &&
+ boot_res.stages == 0 &&
+ boot_res.result == 0) {
+ my_puts_P(PSTR("Booting...\n"));
+ } else {
+ z80_bus_cmd(Reset);
+ boot_res.stages++;
+ printf_P(PSTR("Bootloader stopped at stage %d, result: %d, IDE stat/error: 0x%.02x/0x%.02x\n"),
+ boot_param.stages - boot_res.stages,
+ 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, uint_fast8_t flag, int argc, char * const argv[])
{
uint16_t count=1;
}
if (argc > 1)
- count = (uint16_t) strtoul(argv[1], NULL, 16);
+ count = (uint16_t) eval_arg(argv[1], NULL);
z80_bus_cmd(Request);
while (count--)
}
-command_ret_t do_go(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+command_ret_t do_go(cmd_tbl_t *cmdtp, uint_fast8_t flag, int argc, char * const argv[])
{
uint32_t addr;
if (argc < 2)
return CMD_RET_USAGE;
- addr = strtoul(argv[1], NULL, 16);
+ addr = eval_arg(argv[1], NULL);
if (addr >= (1UL<<16)) {
printf_P(PSTR("## Startaddress 0x%05lx too high.\n"
" (Out of logical address space (0x00000-0x0ffff))\n"),
}
-command_ret_t do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+command_ret_t do_reset(cmd_tbl_t *cmdtp, uint_fast8_t flag, int argc, char * const argv[])
{
(void) cmdtp; (void) flag; (void) argc; (void) argv;
return CMD_RET_SUCCESS;
}
-command_ret_t do_restart(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+command_ret_t do_restart(cmd_tbl_t *cmdtp, uint_fast8_t flag, int argc, char * const argv[])
{
(void) cmdtp; (void) flag; (void) argc; (void) argv;
), esc + 0x40);
}
-command_ret_t do_console(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+command_ret_t do_console(cmd_tbl_t *cmdtp, uint_fast8_t flag, int argc, char * const argv[])
{
int ch;
uint8_t pending;