aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJavier <dev.git@javispedro.com>2026-11-01 02:07:26 +0100
committerJavier <dev.git@javispedro.com>2026-11-01 02:07:26 +0100
commitc1ec955152b48b7938d20e9cba8b6e67479c2e73 (patch)
treef2fcff55d7a4d9962d08c973f7d49810f213954e
parent2b80e7e349eeb6b5839577946cff962470d57c21 (diff)
downloadchu-c1ec955152b48b7938d20e9cba8b6e67479c2e73.tar.gz
chu-c1ec955152b48b7938d20e9cba8b6e67479c2e73.zip
add a signature mechanism for ioctl control strings
-rw-r--r--dos/chud.c52
-rw-r--r--dos/chudisk.c22
-rw-r--r--dos/chudisk.h14
-rw-r--r--dos/inc/dosapi.h4
4 files changed, 73 insertions, 19 deletions
diff --git a/dos/chud.c b/dos/chud.c
index c6d728c..498d97b 100644
--- a/dos/chud.c
+++ b/dos/chud.c
@@ -20,11 +20,13 @@
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
+#include <errno.h>
#include <dos.h>
#include <dosfunc.h>
#include <io.h>
#include "inc/mbr.h"
+#include "inc/dosapi.h"
#include "inc/dosdrv.h"
#include "chudisk.h"
@@ -56,11 +58,10 @@ static int ioctl_read_control(uint8_t drive, void *buffer, int len)
regs.x.dx = FP_OFF(buffer);
intdos(&regs, &regs);
-
if (regs.x.cflag) {
- return -1;
+ return -1; // Generic error, but errno should be properly set
} else {
- return regs.x.ax;
+ return regs.x.ax; // Number of bytes read
}
}
@@ -74,7 +75,6 @@ static int ioctl_write_control(uint8_t drive, void *buffer, int len)
regs.x.dx = FP_OFF(buffer);
intdos(&regs, &regs);
-
if (regs.x.cflag) {
return -1;
} else {
@@ -98,9 +98,34 @@ static int ioctl_read_abs_sector(uint8_t drive, void *buffer, uint32_t sector, i
regs.h.cl = CHUDISK_IOCTL_DISK_READ_ABS_SECTOR;
regs.x.dx = FP_OFF(&ciod);
- intdos(&regs, &regs);
-
- return regs.x.cflag ? -1 : 0;
+ if (intdos(&regs, &regs) == 0) {
+ return 0;
+ } else {
+ struct DOSERROR err;
+ // Get the extended error from DOS, more useful than a simple EACCES
+ // and translate to watcom's errno
+ switch (dosexterr(&err)) {
+ case DOS_ERROR_INVALID_FUNCTION:
+ errno = EINVAL;
+ break;
+ case DOS_ERROR_FILE_NOT_FOUND:
+ case DOS_ERROR_PATH_NOT_FOUND:
+ errno = ENOENT;
+ break;
+ case DOS_ERROR_INVALID_DRIVE:
+ errno = ENODEV;
+ break;
+ case DOS_ERROR_READ_FAULT:
+ case DOS_ERROR_WRITE_FAULT:
+ case DOS_ERROR_GEN_FAILURE:
+ errno = EIO;
+ break;
+ default:
+ errno = EFAULT;
+ break;
+ }
+ return -errno;
+ }
}
static void dos_disk_reset()
@@ -123,6 +148,11 @@ static int parse_chudisk_control_string(const char *b, int len)
}
i = 0;
#endif
+ // signature
+ if (b[i] != 'C' || b[i+1] != 'H') {
+ return -1;
+ }
+ i+=2;
while (i < len) {
char c = b[i++];
switch (c) {
@@ -345,7 +375,7 @@ static void usage()
int main(int argc, const char *argv[])
{
- static char buffer[16];
+ static char buffer[32];
int i;
unsigned part;
@@ -399,10 +429,12 @@ int main(int argc, const char *argv[])
dos_disk_reset(); // Flush caches before we swap the drive...
i = 0;
- buffer[i++] = 'S';
+ buffer[i++] = 'C'; // Signature
+ buffer[i++] = 'H';
+ buffer[i++] = 'S'; // Partition start sector
memcpy(&buffer[i], &partinfo[part-1].start_sector, sizeof(uint32_t));
i+=sizeof(uint32_t);
- buffer[i++] = 'L';
+ buffer[i++] = 'L'; // Partition len
memcpy(&buffer[i], &partinfo[part-1].num_sectors, sizeof(uint32_t));
i+=sizeof(uint32_t);
buffer[i] = '\0';
diff --git a/dos/chudisk.c b/dos/chudisk.c
index c7c0968..d822110 100644
--- a/dos/chudisk.c
+++ b/dos/chudisk.c
@@ -598,10 +598,13 @@ void interrupt_routine()
return;
}
// If there's enough space, return our internal config string.
- if (saved_drs->cmd.ioctlrw.len >= 3 + 2 + 1 + 5 + 1) {
+ if (saved_drs->cmd.ioctlrw.len >= 2 + /*B*/3 + /*3*/2 + /*R*/2 + /*S*/5 + /*L*/5 + 1) {
uint8_t far * buf = saved_drs->cmd.ioctlrw.buffer;
int len = 0;
- // B = base port (2 byte)
+ // signature (2 bytes)
+ buf[len++] = 'C';
+ buf[len++] = 'H';
+ // B = base port (2 bytes)
buf[len++] = 'B';
_fmemcpy(&buf[len], &ch375_dev.io_base, sizeof(ch375_dev.io_base));
len += sizeof(ch375_dev.io_base);
@@ -615,6 +618,10 @@ void interrupt_routine()
buf[len++] = 'S';
_fmemcpy(&buf[len], &data.unit[saved_drs->unit].start_sector, sizeof(uint32_t));
len += sizeof(uint32_t);
+ // L = partition len (4 bytes)
+ buf[len++] = 'L';
+ _fmemcpy(&buf[len], &data.unit[saved_drs->unit].sectors, sizeof(uint32_t));
+ len += sizeof(uint32_t);
buf[len++] = '\0';
saved_drs->cmd.ioctlrw.len = len;
} else {
@@ -632,7 +639,14 @@ void interrupt_routine()
if (saved_drs->cmd.ioctlrw.len >= 2) {
uint8_t far * buf = saved_drs->cmd.ioctlrw.buffer;
int i = 0;
- do {
+ if (buf[i] != 'C' || buf[i+1] != 'H') {
+ dprintf(" invalid signature\n");
+ saved_drs->cmd.ioctlrw.len = 0;
+ saved_drs->status = DOS_DD_ERR_UNKNOWN_COMMAND | DOS_DD_STATUS_ERROR_DONE;
+ return;
+ }
+ i += 2;
+ while (i < saved_drs->cmd.ioctlrw.len) {
char c = buf[i++];
switch (c) {
case 'S': // Partition start (5 bytes)
@@ -659,7 +673,7 @@ void interrupt_routine()
saved_drs->status = DOS_DD_ERR_WRITE_FAULT | DOS_DD_STATUS_ERROR_DONE;
return;
}
- } while (i < saved_drs->cmd.ioctlrw.len);
+ }
} else {
saved_drs->cmd.ioctlrw.len = 0;
saved_drs->status = DOS_DD_ERR_WRITE_FAULT | DOS_DD_STATUS_ERROR_DONE;
diff --git a/dos/chudisk.h b/dos/chudisk.h
index 1d2fbe4..bc7f12d 100644
--- a/dos/chudisk.h
+++ b/dos/chudisk.h
@@ -54,7 +54,7 @@ extern struct chudisk_data
struct chudisk_unit {
/** Whether the partition exists (start_sector points to it) */
bool exists;
- /** Note in theory may be zero (superfloppy) */
+ /** Start sector of partition. Note in theory may be zero (superfloppy) */
uint32_t start_sector;
/** Number of sectors for this partition. */
uint32_t sectors;
@@ -78,15 +78,21 @@ extern uint8_t wait_for_ch375_result(unsigned int max_ticks);
// TODO Not sure we can really happily add custom minors here,
// but then again DOS outright refuses to accept any other major
enum CHUDISK_IOCTL_DISK_MINOR {
+ /** Read an absolute disk sector.
+ * This ignores any configured partition on this unit. */
CHUDISK_IOCTL_DISK_READ_ABS_SECTOR = 0xC1
};
typedef _Packed union CHUDISK_IOCTL_DISK_DATA
{
+ /* @see CHUDISK_IOCTL_DISK_READ_ABS_SECTOR */
struct CHUDISK_RWABSSECTOR {
- uint32_t sector;
- uint8_t sectors;
- void far * buffer;
+ /** Absolute starting sector. */
+ uint32_t sector;
+ /** Number of sectors to read. */
+ uint8_t sectors;
+ /** Buffer to read data into. */
+ void far * buffer;
} rwabs;
} CHUDISK_IOCTL_DISK_DATA;
diff --git a/dos/inc/dosapi.h b/dos/inc/dosapi.h
index 18dbde0..8295660 100644
--- a/dos/inc/dosapi.h
+++ b/dos/inc/dosapi.h
@@ -57,7 +57,9 @@ enum dos_error {
DOS_ERROR_SEEK = 25,
DOS_ERROR_NOT_DOS_DISK = 26,
DOS_ERROR_SECTOR_NOT_FOUND = 27,
-
+ DOS_ERROR_OUT_OF_PAPER = 28,
+ DOS_ERROR_WRITE_FAULT = 29,
+ DOS_ERROR_READ_FAULT = 30,
DOS_ERROR_GEN_FAILURE = 31,
DOS_ERROR_HANDLE_EOF = 38,