xref: /netbsd-src/sys/arch/i386/stand/dosboot/dosfile.c (revision c1022ef173835a71dc7d8d5b041be2daa84028d7)
1*c1022ef1Srin /*	$NetBSD: dosfile.c,v 1.2 2024/06/29 13:46:40 rin Exp $	 */
21ecb4f3fSrin 
31ecb4f3fSrin /*
41ecb4f3fSrin  * Copyright (c) 1996
51ecb4f3fSrin  *	Matthias Drochner.  All rights reserved.
61ecb4f3fSrin  *
71ecb4f3fSrin  * Redistribution and use in source and binary forms, with or without
81ecb4f3fSrin  * modification, are permitted provided that the following conditions
91ecb4f3fSrin  * are met:
101ecb4f3fSrin  * 1. Redistributions of source code must retain the above copyright
111ecb4f3fSrin  *    notice, this list of conditions and the following disclaimer.
121ecb4f3fSrin  * 2. Redistributions in binary form must reproduce the above copyright
131ecb4f3fSrin  *    notice, this list of conditions and the following disclaimer in the
141ecb4f3fSrin  *    documentation and/or other materials provided with the distribution.
151ecb4f3fSrin  *
161ecb4f3fSrin  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
171ecb4f3fSrin  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
181ecb4f3fSrin  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
191ecb4f3fSrin  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
201ecb4f3fSrin  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
211ecb4f3fSrin  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
221ecb4f3fSrin  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
231ecb4f3fSrin  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
241ecb4f3fSrin  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
251ecb4f3fSrin  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
261ecb4f3fSrin  *
271ecb4f3fSrin  */
281ecb4f3fSrin 
291ecb4f3fSrin /*
301ecb4f3fSrin  * DOS filesystem for libsa
311ecb4f3fSrin  * standalone - uses no device, works only with DOS running
321ecb4f3fSrin  * needs lowlevel parts from dos_file.S
331ecb4f3fSrin  */
341ecb4f3fSrin 
351ecb4f3fSrin #include <lib/libsa/stand.h>
361ecb4f3fSrin 
371ecb4f3fSrin #include "diskbuf.h"
381ecb4f3fSrin #include "dosfile.h"
391ecb4f3fSrin 
401ecb4f3fSrin struct dosfile {
411ecb4f3fSrin 	int doshandle, off;
421ecb4f3fSrin };
431ecb4f3fSrin 
441ecb4f3fSrin extern int doserrno;	/* in dos_file.S */
451ecb4f3fSrin 
461ecb4f3fSrin static int dos2errno(void);
471ecb4f3fSrin 
481ecb4f3fSrin static int
dos2errno(void)491ecb4f3fSrin dos2errno(void)
501ecb4f3fSrin {
511ecb4f3fSrin 	int err;
521ecb4f3fSrin 
531ecb4f3fSrin 	switch (doserrno) {
541ecb4f3fSrin 	    case 1: /* invalid function number */
551ecb4f3fSrin 	    case 4: /* too many open files */
561ecb4f3fSrin 	    case 12: /* invalid access mode */
571ecb4f3fSrin 	    default:
581ecb4f3fSrin 		err = EIO;
591ecb4f3fSrin 		break;
601ecb4f3fSrin 	    case 2: /* file not found */
611ecb4f3fSrin 	    case 3: /* path not found */
621ecb4f3fSrin 		err = ENOENT;
631ecb4f3fSrin 		break;
641ecb4f3fSrin 	    case 5: /* access denied */
651ecb4f3fSrin 		err = EPERM;
661ecb4f3fSrin 		break;
671ecb4f3fSrin 	    case 6: /* invalid handle */
681ecb4f3fSrin 		err = EINVAL;
691ecb4f3fSrin 		break;
701ecb4f3fSrin 	}
711ecb4f3fSrin 	return err;
721ecb4f3fSrin }
731ecb4f3fSrin 
741ecb4f3fSrin __compactcall int
dos_open(const char * path,struct open_file * f)751ecb4f3fSrin dos_open(const char *path, struct open_file *f)
761ecb4f3fSrin {
771ecb4f3fSrin 	struct dosfile *df;
781ecb4f3fSrin 
791ecb4f3fSrin 	df = (struct dosfile *) alloc(sizeof(*df));
801ecb4f3fSrin 	if (!df)
811ecb4f3fSrin 		return -1;
821ecb4f3fSrin 
831ecb4f3fSrin 	df->off = 0;
841ecb4f3fSrin 	df->doshandle = dosopen(path);
851ecb4f3fSrin 	if (df->doshandle < 0) {
861ecb4f3fSrin #ifdef DEBUG
871ecb4f3fSrin 		printf("DOS error %d\n", doserrno);
881ecb4f3fSrin #endif
891ecb4f3fSrin 		dealloc(df, sizeof(*df));
901ecb4f3fSrin 		return dos2errno();
911ecb4f3fSrin 	}
921ecb4f3fSrin 	f->f_fsdata = (void *) df;
931ecb4f3fSrin 	return 0;
941ecb4f3fSrin }
951ecb4f3fSrin 
961ecb4f3fSrin __compactcall int
dos_read(struct open_file * f,void * addr,size_t size,size_t * resid)971ecb4f3fSrin dos_read(struct open_file *f, void *addr, size_t size, size_t *resid)
981ecb4f3fSrin {
991ecb4f3fSrin 	struct dosfile *df;
1001ecb4f3fSrin 	int             got;
1011ecb4f3fSrin 	static int      tc = 0;
1021ecb4f3fSrin 
1031ecb4f3fSrin 	df = (struct dosfile *) f->f_fsdata;
1041ecb4f3fSrin 
1051ecb4f3fSrin 	if (!(tc++ % 4))
1061ecb4f3fSrin 		twiddle();
1071ecb4f3fSrin 
1081ecb4f3fSrin 	if ((unsigned long) addr >= 0x10000) {
1091ecb4f3fSrin 		u_int           lsize = size;
1101ecb4f3fSrin 
1111ecb4f3fSrin 		while (lsize > 0) {
1121ecb4f3fSrin 			u_int           tsize;
1131ecb4f3fSrin 			size_t          tgot;
1141ecb4f3fSrin 			char		*p = addr;
1151ecb4f3fSrin 
1161ecb4f3fSrin 			tsize = lsize;
1171ecb4f3fSrin 
1181ecb4f3fSrin 			if (tsize > DISKBUFSIZE)
1191ecb4f3fSrin 				tsize = DISKBUFSIZE;
1201ecb4f3fSrin 
1211ecb4f3fSrin 			alloc_diskbuf(dos_read);
1221ecb4f3fSrin 
1231ecb4f3fSrin 			tgot = dosread(df->doshandle, diskbufp, tsize);
1241ecb4f3fSrin 			if (tgot < 0) {
1251ecb4f3fSrin #ifdef DEBUG
1261ecb4f3fSrin 				printf("DOS error %d\n", doserrno);
1271ecb4f3fSrin #endif
1281ecb4f3fSrin 				return dos2errno();
1291ecb4f3fSrin 			}
1301ecb4f3fSrin 			memcpy(p, diskbufp, tgot);
1311ecb4f3fSrin 
1321ecb4f3fSrin 			p += tgot;
1331ecb4f3fSrin 			lsize -= tgot;
1341ecb4f3fSrin 
1351ecb4f3fSrin 			if (tgot != tsize)
1361ecb4f3fSrin 				break;	/* EOF */
1371ecb4f3fSrin 		}
1381ecb4f3fSrin 		got = size - lsize;
1391ecb4f3fSrin 	} else {
1401ecb4f3fSrin 		got = dosread(df->doshandle, addr, size);
1411ecb4f3fSrin 
1421ecb4f3fSrin 		if (got < 0) {
1431ecb4f3fSrin #ifdef DEBUG
1441ecb4f3fSrin 			printf("DOS error %d\n", doserrno);
1451ecb4f3fSrin #endif
1461ecb4f3fSrin 			return dos2errno();
1471ecb4f3fSrin 		}
1481ecb4f3fSrin 	}
1491ecb4f3fSrin 
1501ecb4f3fSrin 	df->off += got;
1511ecb4f3fSrin 	size -= got;
1521ecb4f3fSrin 
1531ecb4f3fSrin 	if (resid)
1541ecb4f3fSrin 		*resid = size;
1551ecb4f3fSrin 	return 0;
1561ecb4f3fSrin }
1571ecb4f3fSrin 
1581ecb4f3fSrin __compactcall int
dos_close(struct open_file * f)1591ecb4f3fSrin dos_close(struct open_file *f)
1601ecb4f3fSrin {
1611ecb4f3fSrin 	struct dosfile *df;
1621ecb4f3fSrin 	df = (struct dosfile *) f->f_fsdata;
1631ecb4f3fSrin 
1641ecb4f3fSrin 	dosclose(df->doshandle);
1651ecb4f3fSrin 
1661ecb4f3fSrin 	if (df)
1671ecb4f3fSrin 		dealloc(df, sizeof(*df));
1681ecb4f3fSrin 	return 0;
1691ecb4f3fSrin }
1701ecb4f3fSrin 
1711ecb4f3fSrin __compactcall int
dos_write(struct open_file * f,void * start,size_t size,size_t * resid)1721ecb4f3fSrin dos_write(struct open_file *f, void *start, size_t size, size_t *resid)
1731ecb4f3fSrin {
1741ecb4f3fSrin 	return EROFS;
1751ecb4f3fSrin }
1761ecb4f3fSrin 
1771ecb4f3fSrin __compactcall int
dos_stat(struct open_file * f,struct stat * sb)1781ecb4f3fSrin dos_stat(struct open_file *f, struct stat *sb)
1791ecb4f3fSrin {
1801ecb4f3fSrin 	sb->st_mode = 0444;
1811ecb4f3fSrin 	sb->st_nlink = 1;
1821ecb4f3fSrin 	sb->st_uid = 0;
1831ecb4f3fSrin 	sb->st_gid = 0;
1841ecb4f3fSrin 	sb->st_size = -1;
1851ecb4f3fSrin 	return 0;
1861ecb4f3fSrin }
1871ecb4f3fSrin 
1881ecb4f3fSrin __compactcall off_t
dos_seek(struct open_file * f,off_t offset,int where)1891ecb4f3fSrin dos_seek(struct open_file *f, off_t offset, int where)
1901ecb4f3fSrin {
1911ecb4f3fSrin 	struct dosfile *df;
1921ecb4f3fSrin 	int             doswhence, res;
1931ecb4f3fSrin #ifdef DOS_CHECK
1941ecb4f3fSrin 	int             checkoffs;
1951ecb4f3fSrin #endif
1961ecb4f3fSrin 	df = (struct dosfile *) f->f_fsdata;
1971ecb4f3fSrin 
1981ecb4f3fSrin 	switch (where) {
1991ecb4f3fSrin 	case SEEK_SET:
2001ecb4f3fSrin 		doswhence = 0;
2011ecb4f3fSrin #ifdef DOS_CHECK
2021ecb4f3fSrin 		checkoffs = offset;	/* don't trust DOS */
2031ecb4f3fSrin #endif
2041ecb4f3fSrin 		break;
2051ecb4f3fSrin 	case SEEK_CUR:
2061ecb4f3fSrin 		doswhence = 1;
2071ecb4f3fSrin #ifdef DOS_CHECK
2081ecb4f3fSrin 		checkoffs = df->off + offset;
2091ecb4f3fSrin #endif
2101ecb4f3fSrin 		break;
2111ecb4f3fSrin 	case SEEK_END:
2121ecb4f3fSrin 		doswhence = 2;
2131ecb4f3fSrin #ifdef DOS_CHECK
2141ecb4f3fSrin 		checkoffs = -1;	/* we dont know len */
2151ecb4f3fSrin #endif
2161ecb4f3fSrin 		break;
2171ecb4f3fSrin 	default:
2181ecb4f3fSrin 		errno = EOFFSET;
2191ecb4f3fSrin 		return -1;
2201ecb4f3fSrin 	}
2211ecb4f3fSrin 	res = dosseek(df->doshandle, offset, doswhence);
2221ecb4f3fSrin 	if (res == -1) {
2231ecb4f3fSrin 		errno = dos2errno();
2241ecb4f3fSrin 		return -1;
2251ecb4f3fSrin 	}
2261ecb4f3fSrin #ifdef DOS_CHECK
2271ecb4f3fSrin 	if ((checkoffs != -1) && (res != checkoffs)) {
2281ecb4f3fSrin 		printf("dosfile: unexpected seek result (%d+%d(%d)=%d)\n",
2291ecb4f3fSrin 		       df->off, offset, where, res);
2301ecb4f3fSrin 		errno = EOFFSET;
2311ecb4f3fSrin 		return -1;
2321ecb4f3fSrin 	}
2331ecb4f3fSrin #endif
2341ecb4f3fSrin 	df->off = res;
2351ecb4f3fSrin 	return res;
2361ecb4f3fSrin }
237