diff options
| author | Javier <dev.git@javispedro.com> | 2026-11-01 02:07:26 +0100 |
|---|---|---|
| committer | Javier <dev.git@javispedro.com> | 2026-11-01 02:07:26 +0100 |
| commit | c1ec955152b48b7938d20e9cba8b6e67479c2e73 (patch) | |
| tree | f2fcff55d7a4d9962d08c973f7d49810f213954e /dos | |
| parent | 2b80e7e349eeb6b5839577946cff962470d57c21 (diff) | |
| download | chu-c1ec955152b48b7938d20e9cba8b6e67479c2e73.tar.gz chu-c1ec955152b48b7938d20e9cba8b6e67479c2e73.zip | |
add a signature mechanism for ioctl control strings
Diffstat (limited to 'dos')
| -rw-r--r-- | dos/chud.c | 52 | ||||
| -rw-r--r-- | dos/chudisk.c | 22 | ||||
| -rw-r--r-- | dos/chudisk.h | 14 | ||||
| -rw-r--r-- | dos/inc/dosapi.h | 4 |
4 files changed, 73 insertions, 19 deletions
@@ -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(®s, ®s); - 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(®s, ®s); - 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(®s, ®s); - - return regs.x.cflag ? -1 : 0; + if (intdos(®s, ®s) == 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, |
