/*
* (C) Copyright 2015 Leo C. <erbl259-lmu@yahoo.de>
*
- * SPDX-License-Identifier: GPL-2.0+
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+/*
+ * See CP/M 3 System Manual, Appendix D: CPM3.SYS File Format
*/
#include "common.h"
#define RS 128 /* CP/M record size */
+#define FSIZE_t DWORD
+
/*
* Load Routine
*
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;
unsigned int br; /* bytes read */
uint8_t buffer[RS];
(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);
if (argc > 2)
- banked_base = strtoul(argv[2], NULL, 16);
+ common_base = strtoul(argv[2], NULL, 16);
- fname = getenv(PSTR(ENV_CPM3_SYSFILE));
- if (argc > 2) {
- fname = argv[2];
+ fname = getenv_char(PSTR(ENV_CPM3_SYSFILE));
+ if (argc > 1) {
+ fname = argv[1];
}
if (fname == NULL || *fname == '\0')
fname = default_fname;
*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 */