]> cloudbase.mooo.com Git - z180-stamp.git/blobdiff - avr/cmd_loadcpm3.c
new command: boot - boot default, i.e., run 'bootcmd'
[z180-stamp.git] / avr / cmd_loadcpm3.c
index da1be375526aee63bce44ac656c490d2ddaa2c42..6ccb3f9597245f05081747187b59ebf9c837da26 100644 (file)
@@ -1,18 +1,19 @@
 /*
- * (C) Copyright 2015 Leo C. <erbl259-lmu@yahoo.de>
+ * (C) Copyright 2015,2016 Leo C. <erbl259-lmu@yahoo.de>
  *
- * SPDX-License-Identifier:    GPL-2.0+
+ * SPDX-License-Identifier:    GPL-2.0
  */
 
-#include "common.h"
-#include <stdlib.h>
+/*
+ * See CP/M 3 System Manual, Appendix D: CPM3.SYS File Format
+ */
+
+#include "cmd_loadcpm3.h"
 #include <ctype.h>
-#include <string.h>
-#include <stdbool.h>
 
-#include "command.h"
 #include "env.h"
 #include "ff.h"
+#include "eval_arg.h"
 #include "con-utils.h"
 #include "z80-if.h"
 #include "debug.h"
@@ -20,6 +21,8 @@
 
 #define RS             128             /* CP/M record size */
 
+#define FSIZE_t DWORD
+
 /*
  *     Load Routine
  *
@@ -57,18 +60,18 @@ int load(FIL *File, uint32_t addr, uint8_t len)
 
 #pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
 
-command_ret_t do_loadcpm3(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+command_ret_t do_loadcpm3(cmd_tbl_t *cmdtp, uint_fast8_t flag, int argc, char * const argv[])
 {
        uint16_t mem_top;
        uint8_t res_len;
        uint16_t bank_top;
        uint8_t bank_len;
        uint16_t osentry_addr = 0;
-       uint32_t common_base, banked_base;
+       uint32_t common_base = 0;
+       uint32_t banked_base;
        char *fname;
        FIL File;
-       /* TODO: put CONFIG_CPM3_SYSFILE in flash */
-       char default_fname[] = CONFIG_CPM3_SYSFILE;
+       char default_fname[strlen_P(PSTR(CONFIG_CPM3_SYSFILE)) + 1];
        unsigned int br;                                        /* bytes read */
        uint8_t buffer[RS];
        int res;
@@ -76,22 +79,24 @@ command_ret_t do_loadcpm3(cmd_tbl_t *cmdtp, int flag, int argc, char * const arg
        (void) cmdtp; (void) flag;
 
 
-       common_base = getenv_ulong(PSTR(ENV_CPM3_COMMON_BASE), 16,
-                                               CONFIG_CPM3_COMMON_BASE);
+       //common_base = getenv_ulong(PSTR(ENV_CPM3_COMMON_BASE), 16,
+       //                                      CONFIG_CPM3_COMMON_BASE);
        banked_base = getenv_ulong(PSTR(ENV_CPM3_BANKED_BASE), 16,
                                                CONFIG_CPM3_BANKED_BASE);
 
        if (argc > 3)
-               banked_base = strtoul(argv[3], NULL, 16);
+               banked_base = eval_arg(argv[3], NULL);
        if (argc > 2)
-               banked_base = strtoul(argv[2], NULL, 16);
+               common_base = eval_arg(argv[2], NULL);
 
-       fname = getenv(PSTR(ENV_CPM3_SYSFILE));
-       if (argc > 2) {
-               fname = argv[2];
-       }
-       if (fname == NULL || *fname == '\0')
+       fname = getenv_str(PSTR(ENV_CPM3_SYSFILE));
+       if (fname == NULL || *fname == '\0') {
+               strcpy_P(default_fname, PSTR(CONFIG_CPM3_SYSFILE));
                fname = default_fname;
+       }
+       if (argc > 1) {
+               fname = argv[1];
+       }
 
        res = f_open(&File, fname, FA_READ );
        if (res) {
@@ -123,6 +128,23 @@ command_ret_t do_loadcpm3(cmd_tbl_t *cmdtp, int flag, int argc, char * const arg
        *p = '\0';
        my_puts((char *)buffer);
 
+       if (common_base == 0) {
+               /* read common base
+                * http://www.seasip.info/Cpm/scb.html
+                */
+               FSIZE_t common_base_ofs = ((res_len - 6) << 8)  + 2*RS + RS-7;
+               FSIZE_t cur_pos = f_tell(&File);
+               if ((res = f_lseek(&File, common_base_ofs)) ||
+                               (res = f_read(&File, buffer, 2, &br)) ||
+                               (br != 2) ||
+                               (res = f_lseek(&File, cur_pos)))
+                       goto out;
+               common_base = (uint16_t) buffer[0] + (buffer[1] << 8);
+               setenv_hex(PSTR(ENV_CPM3_COMMON_BASE), common_base);
+       }
+
+       setenv_hex(PSTR(ENV_CPM3_SCB), mem_top - ((res_len - (6 - 1)) << 8) + common_base);
+
        /* Main System Load     */
 
        /* Load Common Portion of System */