Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mfs 100 #2166

Draft
wants to merge 7 commits into
base: devel
Choose a base branch
from
Draft

Mfs 100 #2166

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
60 changes: 50 additions & 10 deletions src/dosext/mfs/lfn.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include "bios.h"
#include "int.h"
#include "lfn.h"
#include "lowmem.h"

#define EOS '\0'
#define BACKSLASH '\\'
Expand Down Expand Up @@ -1133,18 +1134,57 @@ static int mfs_lfn_(void)
call_dos_helper(0x6c);
break;
}
case 0xa0: /* get volume info */
drive = build_posix_path(fpath, src, 0);
if (drive < 0)
return drive + 2;
case 0xa0: { /* get volume info */

struct get_volume_info *s;

/*
* input:
AX = 71A0h
CX = size of buffer
DS:DX -> ASCIZ root name (e.g. "C:\")
ES:DI -> buffer for file system name
return:
AX
BX
CX
DX
buffer filled

*/

src = MK_FP32(_DS, _DX);
dest = SEGOFF2LINEAR(_ES, _DI);
size = _CX;

s = lowmem_alloc(sizeof(*s));
_CX = sizeof(*s);
_DX = 0x0100 | (uint8_t)(toupper(src[0]) - 'A');
_ES = DOSEMU_LMHEAP_SEG;
_DI = DOSEMU_LMHEAP_OFFS_OF(s);

// do int2f/11a0
_AX = 0x11a0;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So I want to call an int2f function from here. Do I need to create something like call_dos_helper(), or is there a better way of doing this?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can use do_int_call_back(0x2f);,
or if you can't - it will assert.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool, will try that out, thanks!

do_int_call_back(0x2f);

// check return value == signature
if (_AX != ((sizeof(*s) << 8) | 0x01)) {
d_printf("LFN: int2f/11a0 return value %x\n", _AX);
lowmem_free(s);
return 0;
}

_AX = 0;
_BX = 0x4002;
_CX = 255;
_DX = 260;
if (size >= 4)
MEMCPY_2DOS(dest, "MFS", 4);
break;
_BX = s->flags_std;
_CX = s->maxfilenamelen;
_DX = s->maxpathlen;
if (size >= s->namelen+1)
MEMCPY_2DOS(dest, s->name, s->namelen+1);

lowmem_free(s);
}
break;

case 0xa1: /* findclose */
d_printf("LFN: findclose %x\n", _BX);
return close_dirhandle(_BX);
Expand Down
4 changes: 2 additions & 2 deletions src/dosext/mfs/mangle.c
Original file line number Diff line number Diff line change
Expand Up @@ -87,13 +87,13 @@ dosaddr_t is_dos_device(const char *path)
*/
if (fname[0] == '/')
{
d_printf("MFS: is_msdos_device %s\n", fname);
d_printf("MFS: is_dos_device %s\n", fname);
p = strrchr(fname,'/');
if (p) fname = p+1; /* strip the directory part */
}
else
{
d_printf("MFS: is_msdos_device %.8s\n", fname);
d_printf("MFS: is_dos_device %.8s\n", fname);
}

/*
Expand Down
75 changes: 69 additions & 6 deletions src/dosext/mfs/mfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,7 @@ static int emufs_loaded = FALSE;
#define EXTENDED_ATTRIBUTES 0x2d /* Used in DOS 4.x */
#define MULTIPURPOSE_OPEN 0x2e /* Used in DOS 4.0+ */

#define GET_VOLUME_INFO 0xa0 /* extension */
#define GET_LARGE_DISK_SPACE 0xa3 /* extension */
#define GET_LARGE_FILE_INFO 0xa6 /* extension */
#define LONG_SEEK 0xc2 /* extension */
Expand Down Expand Up @@ -413,6 +414,8 @@ static const char *redirector_op_to_str(uint8_t op) {

if (op == LONG_SEEK)
return "Long seek (extension)";
else if (op == GET_VOLUME_INFO)
return "Get volume information (extension)";
else if (op == GET_LARGE_DISK_SPACE)
return "Get large disk space (extension)";
else if (op == GET_LARGE_FILE_INFO)
Expand Down Expand Up @@ -629,6 +632,11 @@ select_drive(struct vm86_regs *state, int *drive)
}
break;

case GET_VOLUME_INFO: /* 0xa0 */
/* volume number is in DL (A=0) */
dd = LOW(state->edx);
break;

/* The rest are unknown */
default:
Debug0((dbg_fd, "select_drive() unhandled case %x\n", fn));
Expand Down Expand Up @@ -3347,12 +3355,12 @@ static int dos_fs_redirect(struct vm86_regs *state, char *stk)
return FALSE;
f = &open_files[cnt];
if (f->name == NULL) {
Debug0((dbg_fd, "Close file %x fails\n", f->fd));
Debug0((dbg_fd, "Close file fd=%d fails\n", f->fd));
return FALSE;
}
strlcpy(fpath, f->name, sizeof(fpath));
filename1 = fpath;
Debug0((dbg_fd, "Close file %x (%s)\n", f->fd, filename1));
Debug0((dbg_fd, "Close file fd=%d (%s)\n", f->fd, filename1));

Debug0((dbg_fd, "Handle cnt %d\n", sft_handle_cnt(sft)));
_sft_handle_cnt(sft)--;
Expand Down Expand Up @@ -3578,7 +3586,6 @@ static int dos_fs_redirect(struct vm86_regs *state, char *stk)
}

case GET_DISK_SPACE: { /* 0x0c */
#ifdef USE_DF_AND_AFS_STUFF
cds_t tcds = Addr(state, es, edi);
char *name = cds_current_path(tcds);
unsigned int free, tot, spc, bps;
Expand Down Expand Up @@ -3629,7 +3636,6 @@ static int dos_fs_redirect(struct vm86_regs *state, char *stk)
} else {
Debug0((dbg_fd, "Drive invalid (%s)\n", name));
}
#endif /* USE_DF_AND_AFS_STUFF */
break;
}

Expand Down Expand Up @@ -3916,7 +3922,7 @@ static int dos_fs_redirect(struct vm86_regs *state, char *stk)
do_update_sft(f, fname, fext, sft, drive,
get_dos_attr(fpath, st.st_mode), FCBcall, 1);

Debug0((dbg_fd, "open succeeds: '%s' fd = 0x%x\n", fpath, f->fd));
Debug0((dbg_fd, "open succeeds: '%s' fd=%d\n", fpath, f->fd));
Debug0((dbg_fd, "Size : %ld\n", (long)f->st.st_size));

/* If FCB open requested, we need to call int2f 0x120c */
Expand Down Expand Up @@ -4030,7 +4036,7 @@ static int dos_fs_redirect(struct vm86_regs *state, char *stk)
}

do_update_sft(f, fname, fext, sft, drive, attr, FCBcall, 0);
Debug0((dbg_fd, "create succeeds: '%s' fd = 0x%x\n", fpath, f->fd));
Debug0((dbg_fd, "create succeeds: '%s' fd=%d\n", fpath, f->fd));
Debug0((dbg_fd, "fsize = 0x%"PRIx64"\n", f->size));

/* If FCB open requested, we need to call int2f 0x120c */
Expand Down Expand Up @@ -4508,6 +4514,63 @@ static int dos_fs_redirect(struct vm86_regs *state, char *stk)
return TRUE;
}

case GET_VOLUME_INFO: {
d_printf("MFS: get volume info\n");

// If we get here then select_drive() has determined that 'drive'
// is valid and we own it.

/* input */
/* CX = buffer size */
/* DL = volume number (A=0) (now in drive) */
/* DH = version */
/* ES:DI -> buffer */

/* return */
/* AX = signature */

struct get_volume_info *out = Addr(state, es, edi);

if (WORD(state->ecx) < sizeof(*out)) {
d_printf("MFS: get volume info: caller buffer too small\n");
break;
}

if (HIGH(state->edx) != 1) {
d_printf("MFS: get volume info: caller asked for version (%d)\n", HIGH(state->edx));
break;
}

out->version = 1;
out->size = sizeof(*out);
out->namelen = strlcpy(out->name, "MFS", sizeof(out->name));

/*
* Bit(s) Description (Table 01783)
* 0 searches are case sensitive
* 1 preserves case in directory entries
* 2 uses Unicode characters in file and directory names
* 3-13 reserved (0)
* 14 supports DOS long filename functions
* 15 volume is compressed
*/
out->flags_std = 0b0100000000000010;

/*
* Bit(s) Description (New extension)
* 0 volume is read only
*/
out->flags_ext = 0;
if (read_only(drives[drive]))
out->flags_ext |= 0b0000000000000001;

out->maxfilenamelen = 255;
out->maxpathlen = 260;

SETWORD(&state->eax, (out->size << 8) | out->version);
return TRUE;
}

default:
Debug0((dbg_fd, "Default for undocumented function: %02x\n", (int)LOW(state->eax)));
return REDIRECT;
Expand Down
19 changes: 15 additions & 4 deletions src/dosext/mfs/mfs.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@ Andrew.Tridgell@anu.edu.au 30th March 1993

#define MAX_DRIVES (PRINTER_BASE_DRIVE + MAX_PRINTER + 1)

#define USE_DF_AND_AFS_STUFF

#ifdef __linux__
#define VOLUMELABEL "Linux"
#endif
Expand All @@ -44,8 +42,8 @@ typedef struct vm86_regs state_t;

#define MASK8(x) ((x) & 0xff)
#define MASK16(x) ((x) & 0xffff)
#define HIGH(x) MASK8((unsigned long)(x) >> 8)
#define LOW(x) MASK8((unsigned long)(x))
#define HIGH(x) MASK8((unsigned)(x) >> 8)
#define LOW(x) MASK8((unsigned)(x))
#undef WORD
#define WORD(x) (unsigned)(uint16_t)(x)
#define SETHIGH(x,y) (*(x) = (*(x) & ~0xff00) | ((MASK8(y))<<8))
Expand Down Expand Up @@ -423,3 +421,16 @@ struct file_fd

#define MAX_OPENED_FILES 256
extern struct file_fd open_files[MAX_OPENED_FILES];

struct get_volume_info {
uint8_t version;
uint8_t size; /* size of this structure */
uint8_t namelen; /* length of file system type name */
uint8_t pad;
uint16_t flags_std; /* 15..0 as per RBIL */
uint16_t flags_ext; /* 31..16 for extension */
uint16_t maxfilenamelen;
uint16_t maxpathlen;
char name[16]; /* file system type name */
} __attribute__((packed));
static_assert(sizeof(struct get_volume_info) == 28, "bad GET_VOLUME_INFO structure size");
6 changes: 0 additions & 6 deletions src/plugin/dosdrv/emufs.s
Original file line number Diff line number Diff line change
Expand Up @@ -288,12 +288,6 @@ Error:
movw $0x8003,%ax # Set error
ret

major: .byte 0
minor: .byte 0
sdasize: .word 0
mosver: .word 0
dosver: .word 0

DosemuTooOldMsg:
.ascii "ERROR: Your dosemu is too old, emufs.sys not loaded.\r\n$"

Expand Down