xref: /titanic_53/usr/src/common/fs/hsfs.c (revision f55ce205b4982f6d24998fb468599a00f56b0a7b)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
57c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate  * with the License.
87c478bd9Sstevel@tonic-gate  *
97c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate  * and limitations under the License.
137c478bd9Sstevel@tonic-gate  *
147c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate  *
207c478bd9Sstevel@tonic-gate  * CDDL HEADER END
217c478bd9Sstevel@tonic-gate  */
227c478bd9Sstevel@tonic-gate /*
237c478bd9Sstevel@tonic-gate  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
287c478bd9Sstevel@tonic-gate 
297c478bd9Sstevel@tonic-gate /*
307c478bd9Sstevel@tonic-gate  * Basic file system reading code for standalone I/O system.
317c478bd9Sstevel@tonic-gate  * Simulates a primitive UNIX I/O system (read(), write(), open(), etc).
327c478bd9Sstevel@tonic-gate  * Does not support writes.
337c478bd9Sstevel@tonic-gate  */
347c478bd9Sstevel@tonic-gate 
357c478bd9Sstevel@tonic-gate #include <sys/param.h>
367c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h>
377c478bd9Sstevel@tonic-gate #include <sys/vnode.h>
387c478bd9Sstevel@tonic-gate #include <sys/fs/ufs_fsdir.h>
397c478bd9Sstevel@tonic-gate #include <sys/fs/ufs_fs.h>
407c478bd9Sstevel@tonic-gate #include <sys/fs/ufs_inode.h>
417c478bd9Sstevel@tonic-gate 
427c478bd9Sstevel@tonic-gate #include <sys/fs/hsfs_spec.h>
437c478bd9Sstevel@tonic-gate #include <sys/fs/hsfs_isospec.h>
447c478bd9Sstevel@tonic-gate #include <sys/fs/hsfs_node.h>
457c478bd9Sstevel@tonic-gate #include <sys/fs/hsfs_susp.h>
467c478bd9Sstevel@tonic-gate #include <sys/fs/hsfs_rrip.h>
477c478bd9Sstevel@tonic-gate #include <sys/bootvfs.h>
487c478bd9Sstevel@tonic-gate #include <sys/filep.h>
497c478bd9Sstevel@tonic-gate 
507c478bd9Sstevel@tonic-gate #ifdef	_BOOT
517c478bd9Sstevel@tonic-gate #include "../common/util.h"
527c478bd9Sstevel@tonic-gate #else
537c478bd9Sstevel@tonic-gate #include <sys/sunddi.h>
547c478bd9Sstevel@tonic-gate #endif
557c478bd9Sstevel@tonic-gate 
567c478bd9Sstevel@tonic-gate #define	hdbtodb(n)	((ISO_SECTOR_SIZE / DEV_BSIZE) * (n))
577c478bd9Sstevel@tonic-gate 
587c478bd9Sstevel@tonic-gate #define	HSFS_NUM_SIG    14
597c478bd9Sstevel@tonic-gate 
607c478bd9Sstevel@tonic-gate #define	SUSP_SP_IX	0
617c478bd9Sstevel@tonic-gate #define	SUSP_CE_IX	1
627c478bd9Sstevel@tonic-gate #define	SUSP_PD_IX	2
637c478bd9Sstevel@tonic-gate #define	SUSP_ST_IX	3
647c478bd9Sstevel@tonic-gate #define	SUSP_ER_IX	4
657c478bd9Sstevel@tonic-gate #define	RRIP_PX_IX	5
667c478bd9Sstevel@tonic-gate #define	RRIP_PN_IX	6
677c478bd9Sstevel@tonic-gate #define	RRIP_SL_IX	7
687c478bd9Sstevel@tonic-gate #define	RRIP_CL_IX	8
697c478bd9Sstevel@tonic-gate #define	RRIP_PL_IX	9
707c478bd9Sstevel@tonic-gate #define	RRIP_RE_IX	10
717c478bd9Sstevel@tonic-gate #define	RRIP_RF_IX	11
727c478bd9Sstevel@tonic-gate #define	RRIP_RR_IX	12
737c478bd9Sstevel@tonic-gate #define	RRIP_NM_IX	13
747c478bd9Sstevel@tonic-gate 
757c478bd9Sstevel@tonic-gate #ifdef	_BOOT
767c478bd9Sstevel@tonic-gate #define	dprintf	if (bootrd_debug) printf
777c478bd9Sstevel@tonic-gate #else
787c478bd9Sstevel@tonic-gate #define	printf	kobj_printf
797c478bd9Sstevel@tonic-gate #define	dprintf	if (bootrd_debug) kobj_printf
807c478bd9Sstevel@tonic-gate 
817c478bd9Sstevel@tonic-gate /* PRINTFLIKE1 */
827c478bd9Sstevel@tonic-gate extern void kobj_printf(char *, ...);
837c478bd9Sstevel@tonic-gate #endif
847c478bd9Sstevel@tonic-gate 
857c478bd9Sstevel@tonic-gate extern int bootrd_debug;
867c478bd9Sstevel@tonic-gate extern void *bkmem_alloc(size_t);
877c478bd9Sstevel@tonic-gate extern void bkmem_free(void *, size_t);
887c478bd9Sstevel@tonic-gate 
897c478bd9Sstevel@tonic-gate struct dirstuff {
907c478bd9Sstevel@tonic-gate 	int loc;
917c478bd9Sstevel@tonic-gate 	fileid_t *filep;
927c478bd9Sstevel@tonic-gate };
937c478bd9Sstevel@tonic-gate 
947c478bd9Sstevel@tonic-gate struct hs_direct {
957c478bd9Sstevel@tonic-gate     struct	direct  hs_ufs_dir;
967c478bd9Sstevel@tonic-gate     struct	hs_direntry hs_dir;
977c478bd9Sstevel@tonic-gate };
987c478bd9Sstevel@tonic-gate 
997c478bd9Sstevel@tonic-gate static uint_t root_ino = 0;
1007c478bd9Sstevel@tonic-gate static struct hs_volume *hsfsp;
1017c478bd9Sstevel@tonic-gate static fileid_t *head;
1027c478bd9Sstevel@tonic-gate 
1037c478bd9Sstevel@tonic-gate static char *hsfs_sig_tab[] = {
1047c478bd9Sstevel@tonic-gate 	SUSP_SP,
1057c478bd9Sstevel@tonic-gate 	SUSP_CE,
1067c478bd9Sstevel@tonic-gate 	SUSP_PD,
1077c478bd9Sstevel@tonic-gate 	SUSP_ST,
1087c478bd9Sstevel@tonic-gate 	SUSP_ER,
1097c478bd9Sstevel@tonic-gate 	RRIP_PX,
1107c478bd9Sstevel@tonic-gate 	RRIP_PN,
1117c478bd9Sstevel@tonic-gate 	RRIP_SL,
1127c478bd9Sstevel@tonic-gate 	RRIP_CL,
1137c478bd9Sstevel@tonic-gate 	RRIP_PL,
1147c478bd9Sstevel@tonic-gate 	RRIP_RE,
1157c478bd9Sstevel@tonic-gate 	RRIP_TF,
1167c478bd9Sstevel@tonic-gate 	RRIP_RR,
1177c478bd9Sstevel@tonic-gate 	RRIP_NM
1187c478bd9Sstevel@tonic-gate };
1197c478bd9Sstevel@tonic-gate 
1207c478bd9Sstevel@tonic-gate static int hsfs_num_sig = sizeof (hsfs_sig_tab) / sizeof (hsfs_sig_tab[0]);
1217c478bd9Sstevel@tonic-gate 
1227c478bd9Sstevel@tonic-gate /*
1237c478bd9Sstevel@tonic-gate  *  Local prototypes
1247c478bd9Sstevel@tonic-gate  */
1257c478bd9Sstevel@tonic-gate static struct hs_direct *readdir(struct dirstuff *);
1267c478bd9Sstevel@tonic-gate static uint_t parse_dir(fileid_t *, int, struct hs_direct *);
1277c478bd9Sstevel@tonic-gate static uint_t parse_susp(char *, uint_t *, struct hs_direct *);
1287c478bd9Sstevel@tonic-gate static ino_t dlook(char *, fileid_t *);
1297c478bd9Sstevel@tonic-gate static int opendir(ino_t, fileid_t *);
1307c478bd9Sstevel@tonic-gate static ino_t find(char *, fileid_t *);
1317c478bd9Sstevel@tonic-gate 
1327c478bd9Sstevel@tonic-gate static int bhsfs_mountroot(char *str);
1337c478bd9Sstevel@tonic-gate static int bhsfs_unmountroot(void);
1347c478bd9Sstevel@tonic-gate static int bhsfs_open(char *str, int flags);
1357c478bd9Sstevel@tonic-gate static int bhsfs_close(int fd);
1367c478bd9Sstevel@tonic-gate static void bhsfs_closeall(void);
1377c478bd9Sstevel@tonic-gate static ssize_t bhsfs_read(int fdesc, char *buf, size_t count);
1387c478bd9Sstevel@tonic-gate static off_t bhsfs_lseek(int fdesc, off_t addr, int whence);
1397c478bd9Sstevel@tonic-gate 
1407c478bd9Sstevel@tonic-gate static fileid_t *
1417c478bd9Sstevel@tonic-gate find_fp(int fd)
1427c478bd9Sstevel@tonic-gate {
1437c478bd9Sstevel@tonic-gate 	fileid_t *filep = head;
1447c478bd9Sstevel@tonic-gate 
1457c478bd9Sstevel@tonic-gate 	if (fd >= 0) {
1467c478bd9Sstevel@tonic-gate 		while ((filep = filep->fi_forw) != head)
1477c478bd9Sstevel@tonic-gate 			if (fd == filep->fi_filedes)
1487c478bd9Sstevel@tonic-gate 				return (filep->fi_taken ? filep : 0);
1497c478bd9Sstevel@tonic-gate 	}
1507c478bd9Sstevel@tonic-gate 
1517c478bd9Sstevel@tonic-gate 	return (0);
1527c478bd9Sstevel@tonic-gate }
1537c478bd9Sstevel@tonic-gate 
1547c478bd9Sstevel@tonic-gate static int
1557c478bd9Sstevel@tonic-gate opendir(ino_t inode, fileid_t *filep)
1567c478bd9Sstevel@tonic-gate {
1577c478bd9Sstevel@tonic-gate 	struct hs_direct hsdep;
1587c478bd9Sstevel@tonic-gate 
1597c478bd9Sstevel@tonic-gate 	dprintf("opendir: inode = %ld\n", inode);
1607c478bd9Sstevel@tonic-gate 	/* Set up the IO request */
1617c478bd9Sstevel@tonic-gate 	filep->fi_offset = 0;
1627c478bd9Sstevel@tonic-gate 	filep->fi_blocknum = hdbtodb(inode);
1637c478bd9Sstevel@tonic-gate 	filep->fi_count = ISO_SECTOR_SIZE;
1647c478bd9Sstevel@tonic-gate 	filep->fi_memp = 0;
1657c478bd9Sstevel@tonic-gate 
1667c478bd9Sstevel@tonic-gate 	if (diskread(filep))
1677c478bd9Sstevel@tonic-gate 		return (0);
1687c478bd9Sstevel@tonic-gate 
1697c478bd9Sstevel@tonic-gate 	filep->fi_offset = 0;
1707c478bd9Sstevel@tonic-gate 	filep->fi_blocknum = hdbtodb(inode);
1717c478bd9Sstevel@tonic-gate 
1727c478bd9Sstevel@tonic-gate 	if (inode != root_ino)
1737c478bd9Sstevel@tonic-gate 	    return (0);
1747c478bd9Sstevel@tonic-gate 
1757c478bd9Sstevel@tonic-gate 	if (parse_dir(filep, 0, &hsdep) > 0) {
1767c478bd9Sstevel@tonic-gate 		struct inode *ip;
1777c478bd9Sstevel@tonic-gate 
1787c478bd9Sstevel@tonic-gate 		ip = filep->fi_inode;
1797c478bd9Sstevel@tonic-gate 		if (ip == NULL)
1807c478bd9Sstevel@tonic-gate 			ip = filep->fi_inode = bkmem_alloc(sizeof (*ip));
1817c478bd9Sstevel@tonic-gate 
1827c478bd9Sstevel@tonic-gate 		ip->i_size = hsdep.hs_dir.ext_size;
1837c478bd9Sstevel@tonic-gate 		ip->i_smode = hsdep.hs_dir.mode;
1847c478bd9Sstevel@tonic-gate 		ip->i_number = inode;
1857c478bd9Sstevel@tonic-gate 		return (0);
1867c478bd9Sstevel@tonic-gate 	}
1877c478bd9Sstevel@tonic-gate 	return (1);
1887c478bd9Sstevel@tonic-gate }
1897c478bd9Sstevel@tonic-gate 
1907c478bd9Sstevel@tonic-gate static ino_t
1917c478bd9Sstevel@tonic-gate find(char *path, fileid_t *filep)
1927c478bd9Sstevel@tonic-gate {
1937c478bd9Sstevel@tonic-gate 	char *q;
1947c478bd9Sstevel@tonic-gate 	char c;
1957c478bd9Sstevel@tonic-gate 	ino_t n;
1967c478bd9Sstevel@tonic-gate 
1977c478bd9Sstevel@tonic-gate 	dprintf("find: %s\n", path);
1987c478bd9Sstevel@tonic-gate 	if (path == NULL || *path == '\0')
1997c478bd9Sstevel@tonic-gate 		return (0);
2007c478bd9Sstevel@tonic-gate 
2017c478bd9Sstevel@tonic-gate 	if (opendir(root_ino, filep))
2027c478bd9Sstevel@tonic-gate 		return (0);
2037c478bd9Sstevel@tonic-gate 
2047c478bd9Sstevel@tonic-gate 	while (*path) {
2057c478bd9Sstevel@tonic-gate 		while (*path == '/')
2067c478bd9Sstevel@tonic-gate 			path++;
2077c478bd9Sstevel@tonic-gate 		q = path;
2087c478bd9Sstevel@tonic-gate 		while (*q != '/' && *q != '\0')
2097c478bd9Sstevel@tonic-gate 			q++;
2107c478bd9Sstevel@tonic-gate 		c = *q;
2117c478bd9Sstevel@tonic-gate 		*q = '\0';
212*f55ce205Sszhou 		n = dlook(path, filep);
213*f55ce205Sszhou 		*q = c;
214*f55ce205Sszhou 		path = q;
2157c478bd9Sstevel@tonic-gate 
216*f55ce205Sszhou 		if (n != 0) {
2177c478bd9Sstevel@tonic-gate 			if (c == '\0')
2187c478bd9Sstevel@tonic-gate 				break;
2197c478bd9Sstevel@tonic-gate 			if (opendir(n, filep))
2207c478bd9Sstevel@tonic-gate 				return (0);
2217c478bd9Sstevel@tonic-gate 			continue;
2227c478bd9Sstevel@tonic-gate 		} else {
2237c478bd9Sstevel@tonic-gate 			return (0);
2247c478bd9Sstevel@tonic-gate 		}
2257c478bd9Sstevel@tonic-gate 	}
2267c478bd9Sstevel@tonic-gate 	return ((ino_t)n);
2277c478bd9Sstevel@tonic-gate }
2287c478bd9Sstevel@tonic-gate 
2297c478bd9Sstevel@tonic-gate static ino_t
2307c478bd9Sstevel@tonic-gate dlook(char *s, fileid_t *filep)
2317c478bd9Sstevel@tonic-gate {
2327c478bd9Sstevel@tonic-gate 	struct hs_direct *hsdep;
2337c478bd9Sstevel@tonic-gate 	struct direct *udp;
2347c478bd9Sstevel@tonic-gate 	struct inode *ip;
2357c478bd9Sstevel@tonic-gate 	struct dirstuff dirp;
2367c478bd9Sstevel@tonic-gate 	int len;
2377c478bd9Sstevel@tonic-gate 
2387c478bd9Sstevel@tonic-gate 	dprintf("dlook: %s\n", s);
2397c478bd9Sstevel@tonic-gate 	ip = filep->fi_inode;
2407c478bd9Sstevel@tonic-gate 	if (s == NULL || *s == '\0')
2417c478bd9Sstevel@tonic-gate 		return (0);
2427c478bd9Sstevel@tonic-gate 	if ((ip->i_smode & IFMT) != IFDIR) {
2437c478bd9Sstevel@tonic-gate 		return (0);
2447c478bd9Sstevel@tonic-gate 	}
2457c478bd9Sstevel@tonic-gate 	if (ip->i_size == 0) {
2467c478bd9Sstevel@tonic-gate 		return (0);
2477c478bd9Sstevel@tonic-gate 	}
2487c478bd9Sstevel@tonic-gate 	len = strlen(s);
2497c478bd9Sstevel@tonic-gate 	dirp.loc = 0;
2507c478bd9Sstevel@tonic-gate 	dirp.filep = filep;
2517c478bd9Sstevel@tonic-gate 	for (hsdep = readdir(&dirp); hsdep != NULL; hsdep = readdir(&dirp)) {
2527c478bd9Sstevel@tonic-gate 		udp = &hsdep->hs_ufs_dir;
2537c478bd9Sstevel@tonic-gate 		if (udp->d_namlen == 1 &&
2547c478bd9Sstevel@tonic-gate 		    udp->d_name[0] == '.' &&
2557c478bd9Sstevel@tonic-gate 		    udp->d_name[1] == '\0')
2567c478bd9Sstevel@tonic-gate 			continue;
2577c478bd9Sstevel@tonic-gate 		if (udp->d_namlen == 2 &&
2587c478bd9Sstevel@tonic-gate 		    udp->d_name[0] == '.' &&
2597c478bd9Sstevel@tonic-gate 		    udp->d_name[1] == '.' &&
2607c478bd9Sstevel@tonic-gate 		    udp->d_name[2] == '\0')
2617c478bd9Sstevel@tonic-gate 			continue;
2627c478bd9Sstevel@tonic-gate 		if (udp->d_namlen == len && (strcmp(s, udp->d_name)) == 0) {
2637c478bd9Sstevel@tonic-gate 			struct inode *ip = filep->fi_inode;
2647c478bd9Sstevel@tonic-gate 
2657c478bd9Sstevel@tonic-gate 			filep->fi_offset = 0;
2667c478bd9Sstevel@tonic-gate 			filep->fi_blocknum = hdbtodb(udp->d_ino);
2677c478bd9Sstevel@tonic-gate 
2687c478bd9Sstevel@tonic-gate 			bzero(filep->fi_inode, sizeof (struct inode));
2697c478bd9Sstevel@tonic-gate 			ip->i_size = hsdep->hs_dir.ext_size;
2707c478bd9Sstevel@tonic-gate 			ip->i_smode = hsdep->hs_dir.mode;
2717c478bd9Sstevel@tonic-gate 			ip->i_number = udp->d_ino;
2727c478bd9Sstevel@tonic-gate 			return (udp->d_ino);
2737c478bd9Sstevel@tonic-gate 		}
2747c478bd9Sstevel@tonic-gate 	}
2757c478bd9Sstevel@tonic-gate 	return (0);
2767c478bd9Sstevel@tonic-gate }
2777c478bd9Sstevel@tonic-gate 
2787c478bd9Sstevel@tonic-gate /*
2797c478bd9Sstevel@tonic-gate  * get next entry in a directory.
2807c478bd9Sstevel@tonic-gate  */
2817c478bd9Sstevel@tonic-gate static struct hs_direct *
2827c478bd9Sstevel@tonic-gate readdir(struct dirstuff *dirp)
2837c478bd9Sstevel@tonic-gate {
2847c478bd9Sstevel@tonic-gate 	static struct hs_direct hsdep;
2857c478bd9Sstevel@tonic-gate 	struct direct *udp = &hsdep.hs_ufs_dir;
2867c478bd9Sstevel@tonic-gate 	struct inode *ip;
2877c478bd9Sstevel@tonic-gate 	fileid_t *filep;
2887c478bd9Sstevel@tonic-gate 	daddr_t lbn;
2897c478bd9Sstevel@tonic-gate 	int off;
2907c478bd9Sstevel@tonic-gate 
2917c478bd9Sstevel@tonic-gate 	dprintf("readdir: start\n");
2927c478bd9Sstevel@tonic-gate 	filep = dirp->filep;
2937c478bd9Sstevel@tonic-gate 	ip = filep->fi_inode;
2947c478bd9Sstevel@tonic-gate 	for (;;) {
2957c478bd9Sstevel@tonic-gate 		if (dirp->loc >= ip->i_size) {
2967c478bd9Sstevel@tonic-gate 			return (NULL);
2977c478bd9Sstevel@tonic-gate 		}
2987c478bd9Sstevel@tonic-gate 		off = dirp->loc & ((1 << ISO_SECTOR_SHIFT) - 1);
2997c478bd9Sstevel@tonic-gate 		if (off == 0) {
3007c478bd9Sstevel@tonic-gate 			lbn = hdbtodb(dirp->loc >> ISO_SECTOR_SHIFT);
3017c478bd9Sstevel@tonic-gate 			filep->fi_blocknum = lbn + hdbtodb(ip->i_number);
3027c478bd9Sstevel@tonic-gate 			filep->fi_count = ISO_SECTOR_SIZE;
3037c478bd9Sstevel@tonic-gate 			filep->fi_memp = 0;
3047c478bd9Sstevel@tonic-gate 			if (diskread(filep)) {
3057c478bd9Sstevel@tonic-gate 				dprintf("readdir: diskread failed\n");
3067c478bd9Sstevel@tonic-gate 				return (NULL);
3077c478bd9Sstevel@tonic-gate 			}
3087c478bd9Sstevel@tonic-gate 		}
3097c478bd9Sstevel@tonic-gate 		dirp->loc += parse_dir(filep, off, &hsdep);
3107c478bd9Sstevel@tonic-gate 		if (udp->d_reclen == 0 && dirp->loc <= ip->i_size) {
3117c478bd9Sstevel@tonic-gate 			dirp->loc = roundup(dirp->loc, ISO_SECTOR_SIZE);
3127c478bd9Sstevel@tonic-gate 			continue;
3137c478bd9Sstevel@tonic-gate 		}
3147c478bd9Sstevel@tonic-gate 		return (&hsdep);
3157c478bd9Sstevel@tonic-gate 	}
3167c478bd9Sstevel@tonic-gate }
3177c478bd9Sstevel@tonic-gate 
3187c478bd9Sstevel@tonic-gate static int
3197c478bd9Sstevel@tonic-gate getblock(fileid_t *filep)
3207c478bd9Sstevel@tonic-gate {
3217c478bd9Sstevel@tonic-gate 	struct inode *ip = filep->fi_inode;
3227c478bd9Sstevel@tonic-gate 	int off, size, diff;
3237c478bd9Sstevel@tonic-gate 	daddr_t lbn;
3247c478bd9Sstevel@tonic-gate 
3257c478bd9Sstevel@tonic-gate 	dprintf("getblock: start\n");
3267c478bd9Sstevel@tonic-gate 	diff = ip->i_size - filep->fi_offset;
3277c478bd9Sstevel@tonic-gate 	if (diff <= 0)
3287c478bd9Sstevel@tonic-gate 		return (-1);
3297c478bd9Sstevel@tonic-gate 
3307c478bd9Sstevel@tonic-gate 	/* which block (or frag) in the file do we read? */
3317c478bd9Sstevel@tonic-gate 	lbn = hdbtodb(filep->fi_offset >> ISO_SECTOR_SHIFT);
3327c478bd9Sstevel@tonic-gate 	filep->fi_blocknum = lbn + hdbtodb(ip->i_number);
3337c478bd9Sstevel@tonic-gate 
3347c478bd9Sstevel@tonic-gate 	off = filep->fi_offset & ((1 << ISO_SECTOR_SHIFT) - 1);
3357c478bd9Sstevel@tonic-gate 	size = filep->fi_count = ISO_SECTOR_SIZE;
3367c478bd9Sstevel@tonic-gate 	filep->fi_memp = 0;
3377c478bd9Sstevel@tonic-gate 	if (diskread(filep))	/* Trap errors */
3387c478bd9Sstevel@tonic-gate 		return (-1);
3397c478bd9Sstevel@tonic-gate 
3407c478bd9Sstevel@tonic-gate 	if (filep->fi_offset - off + size >= ip->i_size)
3417c478bd9Sstevel@tonic-gate 		filep->fi_count = diff + off;
3427c478bd9Sstevel@tonic-gate 	filep->fi_count -= off;
3437c478bd9Sstevel@tonic-gate 	filep->fi_memp += off;
3447c478bd9Sstevel@tonic-gate 	dprintf("getblock: end\n");
3457c478bd9Sstevel@tonic-gate 	return (0);
3467c478bd9Sstevel@tonic-gate }
3477c478bd9Sstevel@tonic-gate 
3487c478bd9Sstevel@tonic-gate static ssize_t
3497c478bd9Sstevel@tonic-gate bhsfs_read(int fd, caddr_t buf, size_t count)
3507c478bd9Sstevel@tonic-gate {
3517c478bd9Sstevel@tonic-gate 	int i, j;
3527c478bd9Sstevel@tonic-gate 	fileid_t *filep;
3537c478bd9Sstevel@tonic-gate 	struct inode *ip;
3547c478bd9Sstevel@tonic-gate 	caddr_t n;
3557c478bd9Sstevel@tonic-gate 
3567c478bd9Sstevel@tonic-gate 	dprintf("bhsfs_read %d, count 0x%lx\n", fd, count);
3577c478bd9Sstevel@tonic-gate 	filep = find_fp(fd);
3587c478bd9Sstevel@tonic-gate 	if (filep == NULL)
3597c478bd9Sstevel@tonic-gate 		return (-1);
3607c478bd9Sstevel@tonic-gate 
3617c478bd9Sstevel@tonic-gate 	ip = filep->fi_inode;
3627c478bd9Sstevel@tonic-gate 	n = buf;
3637c478bd9Sstevel@tonic-gate 	if (filep->fi_offset + count > ip->i_size)
3647c478bd9Sstevel@tonic-gate 		count = ip->i_size - filep->fi_offset;
3657c478bd9Sstevel@tonic-gate 
3667c478bd9Sstevel@tonic-gate 	if ((i = count) <= 0)
3677c478bd9Sstevel@tonic-gate 		return (0);
3687c478bd9Sstevel@tonic-gate 
3697c478bd9Sstevel@tonic-gate 	while (i > 0) {
37030f5cf21Sjg 		if (filep->fi_count == 0) {
3717c478bd9Sstevel@tonic-gate 			if (getblock(filep) == -1)
3727c478bd9Sstevel@tonic-gate 				return (0);
3737c478bd9Sstevel@tonic-gate 		}
3747c478bd9Sstevel@tonic-gate 		j = MIN(i, filep->fi_count);
3757c478bd9Sstevel@tonic-gate 		bcopy(filep->fi_memp, buf, (uint_t)j);
3767c478bd9Sstevel@tonic-gate 		buf += j;
3777c478bd9Sstevel@tonic-gate 		filep->fi_memp += j;
3787c478bd9Sstevel@tonic-gate 		filep->fi_offset += j;
3797c478bd9Sstevel@tonic-gate 		filep->fi_count -= j;
3807c478bd9Sstevel@tonic-gate 		i -= j;
3817c478bd9Sstevel@tonic-gate 	}
3827c478bd9Sstevel@tonic-gate 
3837c478bd9Sstevel@tonic-gate 	dprintf("bhsfs_read: read 0x%x\n", (int)(buf - n));
3847c478bd9Sstevel@tonic-gate 	return (buf - n);
3857c478bd9Sstevel@tonic-gate }
3867c478bd9Sstevel@tonic-gate 
3877c478bd9Sstevel@tonic-gate /*ARGSUSED*/
3887c478bd9Sstevel@tonic-gate static int
3897c478bd9Sstevel@tonic-gate bhsfs_mountroot(char *str)
3907c478bd9Sstevel@tonic-gate {
3917c478bd9Sstevel@tonic-gate 	char *bufp;
3927c478bd9Sstevel@tonic-gate 
3937c478bd9Sstevel@tonic-gate 	if (hsfsp != NULL)
3947c478bd9Sstevel@tonic-gate 		return (0);	/* already mounted */
3957c478bd9Sstevel@tonic-gate 
3967c478bd9Sstevel@tonic-gate 	dprintf("mounting ramdisk as hsfs\n");
3977c478bd9Sstevel@tonic-gate 
3987c478bd9Sstevel@tonic-gate 	hsfsp = bkmem_alloc(sizeof (*hsfsp));
3997c478bd9Sstevel@tonic-gate 	bzero(hsfsp, sizeof (*hsfsp));
4007c478bd9Sstevel@tonic-gate 	head = bkmem_alloc(sizeof (*head));
4017c478bd9Sstevel@tonic-gate 	bzero(head, sizeof (*head));
4027c478bd9Sstevel@tonic-gate 	head->fi_back = head->fi_forw = head;
4037c478bd9Sstevel@tonic-gate 
4047c478bd9Sstevel@tonic-gate 	/* now read the superblock. */
4057c478bd9Sstevel@tonic-gate 	head->fi_blocknum = hdbtodb(ISO_VOLDESC_SEC);
4067c478bd9Sstevel@tonic-gate 	head->fi_offset = 0;
4077c478bd9Sstevel@tonic-gate 	head->fi_count = ISO_SECTOR_SIZE;
4087c478bd9Sstevel@tonic-gate 	head->fi_memp = head->fi_buf;
4097c478bd9Sstevel@tonic-gate 	if (diskread(head)) {
4107c478bd9Sstevel@tonic-gate 		printf("failed to read superblock\n");
4117c478bd9Sstevel@tonic-gate 		bhsfs_closeall();
4127c478bd9Sstevel@tonic-gate 		return (-1);
4137c478bd9Sstevel@tonic-gate 	}
4147c478bd9Sstevel@tonic-gate 
4157c478bd9Sstevel@tonic-gate 	/* Since RRIP is based on ISO9660, that's where we start */
4167c478bd9Sstevel@tonic-gate 	bufp = head->fi_buf;
4177c478bd9Sstevel@tonic-gate 	if ((ISO_DESC_TYPE(bufp) != ISO_VD_PVD) ||
4187c478bd9Sstevel@tonic-gate 	    (strncmp((const char *)ISO_std_id(bufp), ISO_ID_STRING,
4197c478bd9Sstevel@tonic-gate 	    ISO_ID_STRLEN) != 0) || (ISO_STD_VER(bufp) != ISO_ID_VER)) {
4207c478bd9Sstevel@tonic-gate 		dprintf("volume type does not match\n");
4217c478bd9Sstevel@tonic-gate 		bhsfs_closeall();
4227c478bd9Sstevel@tonic-gate 		return (-1);
4237c478bd9Sstevel@tonic-gate 	}
4247c478bd9Sstevel@tonic-gate 
4257c478bd9Sstevel@tonic-gate 	/* Now we fill in the volume descriptor */
4267c478bd9Sstevel@tonic-gate 	hsfsp->vol_size = ISO_VOL_SIZE(bufp);
4277c478bd9Sstevel@tonic-gate 	hsfsp->lbn_size = ISO_BLK_SIZE(bufp);
4287c478bd9Sstevel@tonic-gate 	hsfsp->lbn_shift = ISO_SECTOR_SHIFT;
4297c478bd9Sstevel@tonic-gate 	hsfsp->lbn_secshift = ISO_SECTOR_SHIFT;
4307c478bd9Sstevel@tonic-gate 	hsfsp->vol_set_size = (ushort_t)ISO_SET_SIZE(bufp);
4317c478bd9Sstevel@tonic-gate 	hsfsp->vol_set_seq = (ushort_t)ISO_SET_SEQ(bufp);
4327c478bd9Sstevel@tonic-gate 
4337c478bd9Sstevel@tonic-gate 	/* Make sure we have a valid logical block size */
4347c478bd9Sstevel@tonic-gate 	if (hsfsp->lbn_size & ~(1 << hsfsp->lbn_shift)) {
4357c478bd9Sstevel@tonic-gate 		printf("%d invalid logical block size\n", hsfsp->lbn_size);
4367c478bd9Sstevel@tonic-gate 		bhsfs_closeall();
4377c478bd9Sstevel@tonic-gate 		return (-1);
4387c478bd9Sstevel@tonic-gate 	}
4397c478bd9Sstevel@tonic-gate 
4407c478bd9Sstevel@tonic-gate 	/* Since an HSFS root could be located anywhere on the media! */
4417c478bd9Sstevel@tonic-gate 	root_ino = IDE_EXT_LBN(ISO_root_dir(bufp));
4427c478bd9Sstevel@tonic-gate 	return (0);
4437c478bd9Sstevel@tonic-gate }
4447c478bd9Sstevel@tonic-gate 
4457c478bd9Sstevel@tonic-gate static int
4467c478bd9Sstevel@tonic-gate bhsfs_unmountroot(void)
4477c478bd9Sstevel@tonic-gate {
4487c478bd9Sstevel@tonic-gate 	if (hsfsp == NULL)
4497c478bd9Sstevel@tonic-gate 		return (-1);
4507c478bd9Sstevel@tonic-gate 
4517c478bd9Sstevel@tonic-gate 	bhsfs_closeall();
4527c478bd9Sstevel@tonic-gate 
4537c478bd9Sstevel@tonic-gate 	return (0);
4547c478bd9Sstevel@tonic-gate }
4557c478bd9Sstevel@tonic-gate 
4567c478bd9Sstevel@tonic-gate /*
4577c478bd9Sstevel@tonic-gate  * Open a file.
4587c478bd9Sstevel@tonic-gate  */
4597c478bd9Sstevel@tonic-gate /*ARGSUSED*/
4607c478bd9Sstevel@tonic-gate int
4617c478bd9Sstevel@tonic-gate bhsfs_open(char *str, int flags)
4627c478bd9Sstevel@tonic-gate {
4637c478bd9Sstevel@tonic-gate 	static int filedes = 1;
4647c478bd9Sstevel@tonic-gate 
4657c478bd9Sstevel@tonic-gate 	fileid_t *filep;
4667c478bd9Sstevel@tonic-gate 	ino_t ino;
4677c478bd9Sstevel@tonic-gate 
4687c478bd9Sstevel@tonic-gate 	dprintf("open %s\n", str);
4697c478bd9Sstevel@tonic-gate 	filep = (fileid_t *)bkmem_alloc(sizeof (fileid_t));
4707c478bd9Sstevel@tonic-gate 	filep->fi_back = head->fi_back;
4717c478bd9Sstevel@tonic-gate 	filep->fi_forw = head;
4727c478bd9Sstevel@tonic-gate 	head->fi_back->fi_forw = filep;
4737c478bd9Sstevel@tonic-gate 	head->fi_back = filep;
4747c478bd9Sstevel@tonic-gate 	filep->fi_filedes = filedes++;
4757c478bd9Sstevel@tonic-gate 	filep->fi_taken = 1;
4767c478bd9Sstevel@tonic-gate 	filep->fi_path = (char *)bkmem_alloc(strlen(str) + 1);
4777c478bd9Sstevel@tonic-gate 	(void) strcpy(filep->fi_path, str);
4787c478bd9Sstevel@tonic-gate 	filep->fi_inode = NULL;
4797c478bd9Sstevel@tonic-gate 	bzero(filep->fi_buf, MAXBSIZE);
4807c478bd9Sstevel@tonic-gate 
4817c478bd9Sstevel@tonic-gate 	ino = find(str, filep);
4827c478bd9Sstevel@tonic-gate 	if (ino == 0) {
4837c478bd9Sstevel@tonic-gate 		(void) bhsfs_close(filep->fi_filedes);
4847c478bd9Sstevel@tonic-gate 		return (-1);
4857c478bd9Sstevel@tonic-gate 	}
4867c478bd9Sstevel@tonic-gate 
4877c478bd9Sstevel@tonic-gate 	filep->fi_blocknum = hdbtodb(ino);
4887c478bd9Sstevel@tonic-gate 	filep->fi_offset = 0;
4897c478bd9Sstevel@tonic-gate 	filep->fi_count = 0;
4907c478bd9Sstevel@tonic-gate 	filep->fi_memp = 0;
4917c478bd9Sstevel@tonic-gate 
4927c478bd9Sstevel@tonic-gate 	dprintf("open done\n");
4937c478bd9Sstevel@tonic-gate 	return (filep->fi_filedes);
4947c478bd9Sstevel@tonic-gate }
4957c478bd9Sstevel@tonic-gate 
4967c478bd9Sstevel@tonic-gate int
4977c478bd9Sstevel@tonic-gate bhsfs_close(int fd)
4987c478bd9Sstevel@tonic-gate {
4997c478bd9Sstevel@tonic-gate 	fileid_t *filep;
5007c478bd9Sstevel@tonic-gate 
5017c478bd9Sstevel@tonic-gate 	dprintf("close %d\n", fd);
5027c478bd9Sstevel@tonic-gate 	if (!(filep = find_fp(fd)))
5037c478bd9Sstevel@tonic-gate 		return (-1);
5047c478bd9Sstevel@tonic-gate 
5057c478bd9Sstevel@tonic-gate 	if (filep->fi_taken == 0 || filep == head) {
5067c478bd9Sstevel@tonic-gate 		printf("File descripter %d no allocated!\n", fd);
5077c478bd9Sstevel@tonic-gate 		return (-1);
5087c478bd9Sstevel@tonic-gate 	}
5097c478bd9Sstevel@tonic-gate 
5107c478bd9Sstevel@tonic-gate 	/* unlink and deallocate node */
5117c478bd9Sstevel@tonic-gate 	filep->fi_forw->fi_back = filep->fi_back;
5127c478bd9Sstevel@tonic-gate 	filep->fi_back->fi_forw = filep->fi_forw;
5137c478bd9Sstevel@tonic-gate 	if (filep->fi_inode)
5147c478bd9Sstevel@tonic-gate 		bkmem_free(filep->fi_inode, sizeof (struct inode));
5157c478bd9Sstevel@tonic-gate 	bkmem_free(filep->fi_path, strlen(filep->fi_path) + 1);
5167c478bd9Sstevel@tonic-gate 	bkmem_free((char *)filep, sizeof (fileid_t));
5177c478bd9Sstevel@tonic-gate 	dprintf("close done\n");
5187c478bd9Sstevel@tonic-gate 	return (0);
5197c478bd9Sstevel@tonic-gate }
5207c478bd9Sstevel@tonic-gate 
5217c478bd9Sstevel@tonic-gate static void
5227c478bd9Sstevel@tonic-gate bhsfs_closeall(void)
5237c478bd9Sstevel@tonic-gate {
5247c478bd9Sstevel@tonic-gate 	fileid_t *filep;
5257c478bd9Sstevel@tonic-gate 
5267c478bd9Sstevel@tonic-gate 	while ((filep = head->fi_forw) != head)
5277c478bd9Sstevel@tonic-gate 		if (filep->fi_taken && bhsfs_close(filep->fi_filedes))
5287c478bd9Sstevel@tonic-gate 			printf("Filesystem may be inconsistent.\n");
5297c478bd9Sstevel@tonic-gate 
5307c478bd9Sstevel@tonic-gate 	bkmem_free(hsfsp, sizeof (*hsfsp));
5317c478bd9Sstevel@tonic-gate 	bkmem_free(head, sizeof (fileid_t));
5327c478bd9Sstevel@tonic-gate 	hsfsp = NULL;
5337c478bd9Sstevel@tonic-gate 	head = NULL;
5347c478bd9Sstevel@tonic-gate }
5357c478bd9Sstevel@tonic-gate 
5367c478bd9Sstevel@tonic-gate /*
5377c478bd9Sstevel@tonic-gate  * This version of seek() only performs absolute seeks (whence == 0).
5387c478bd9Sstevel@tonic-gate  */
5397c478bd9Sstevel@tonic-gate static off_t
5407c478bd9Sstevel@tonic-gate bhsfs_lseek(int fd, off_t addr, int whence)
5417c478bd9Sstevel@tonic-gate {
5427c478bd9Sstevel@tonic-gate 	fileid_t *filep;
5437c478bd9Sstevel@tonic-gate 
5447c478bd9Sstevel@tonic-gate 	dprintf("lseek %d, off = %lx\n", fd, addr);
5457c478bd9Sstevel@tonic-gate 	if (!(filep = find_fp(fd)))
5467c478bd9Sstevel@tonic-gate 		return (-1);
5477c478bd9Sstevel@tonic-gate 
5487c478bd9Sstevel@tonic-gate 	switch (whence) {
5497c478bd9Sstevel@tonic-gate 	case SEEK_CUR:
5507c478bd9Sstevel@tonic-gate 		filep->fi_offset += addr;
5517c478bd9Sstevel@tonic-gate 		break;
5527c478bd9Sstevel@tonic-gate 	case SEEK_SET:
5537c478bd9Sstevel@tonic-gate 		filep->fi_offset = addr;
5547c478bd9Sstevel@tonic-gate 		break;
5557c478bd9Sstevel@tonic-gate 	default:
5567c478bd9Sstevel@tonic-gate 	case SEEK_END:
5577c478bd9Sstevel@tonic-gate 		printf("lseek(): invalid whence value %d\n", whence);
5587c478bd9Sstevel@tonic-gate 		break;
5597c478bd9Sstevel@tonic-gate 	}
5607c478bd9Sstevel@tonic-gate 
5617c478bd9Sstevel@tonic-gate 	filep->fi_blocknum = addr / DEV_BSIZE;
5627c478bd9Sstevel@tonic-gate 	filep->fi_count = 0;
5637c478bd9Sstevel@tonic-gate 	return (0);
5647c478bd9Sstevel@tonic-gate }
5657c478bd9Sstevel@tonic-gate 
5667c478bd9Sstevel@tonic-gate /*
5677c478bd9Sstevel@tonic-gate  * Parse a directory entry.
5687c478bd9Sstevel@tonic-gate  *
5697c478bd9Sstevel@tonic-gate  */
5707c478bd9Sstevel@tonic-gate static uint_t
5717c478bd9Sstevel@tonic-gate parse_dir(fileid_t *filep, int offset, struct hs_direct *hsdep)
5727c478bd9Sstevel@tonic-gate {
5737c478bd9Sstevel@tonic-gate 	char *bufp = (char *)(filep->fi_memp + offset);
5747c478bd9Sstevel@tonic-gate 	struct direct *udp = &hsdep->hs_ufs_dir;  /* ufs-style dir info */
5757c478bd9Sstevel@tonic-gate 	struct hs_direntry *hdp = &hsdep->hs_dir; /* hsfs-style dir info */
5767c478bd9Sstevel@tonic-gate 	uint_t ce_lbn;
5777c478bd9Sstevel@tonic-gate 	uint_t ce_len;
5787c478bd9Sstevel@tonic-gate 	uint_t nmlen;
5797c478bd9Sstevel@tonic-gate 	uint_t i;
5807c478bd9Sstevel@tonic-gate 	uchar_t c;
5817c478bd9Sstevel@tonic-gate 
5827c478bd9Sstevel@tonic-gate 	dprintf("parse_dir: offset = %d\n", offset);
5837c478bd9Sstevel@tonic-gate 	/* a zero length dir entry terminates the dir block */
5847c478bd9Sstevel@tonic-gate 	udp->d_reclen = IDE_DIR_LEN(bufp);
5857c478bd9Sstevel@tonic-gate 	if (udp->d_reclen == 0)
5867c478bd9Sstevel@tonic-gate 		return (0);
5877c478bd9Sstevel@tonic-gate 
5887c478bd9Sstevel@tonic-gate 	/* fill in some basic hsfs info */
5897c478bd9Sstevel@tonic-gate 	hdp->ext_lbn  = IDE_EXT_LBN(bufp);
5907c478bd9Sstevel@tonic-gate 	hdp->ext_size = IDE_EXT_SIZE(bufp);
5917c478bd9Sstevel@tonic-gate 	hdp->xar_len  = IDE_XAR_LEN(bufp);
5927c478bd9Sstevel@tonic-gate 	hdp->intlf_sz = IDE_INTRLV_SIZE(bufp);
5937c478bd9Sstevel@tonic-gate 	hdp->intlf_sk = IDE_INTRLV_SKIP(bufp);
5947c478bd9Sstevel@tonic-gate 	hdp->sym_link = NULL;
5957c478bd9Sstevel@tonic-gate 
5967c478bd9Sstevel@tonic-gate 	/* we use lbn of data extent as an inode # equivalent */
5977c478bd9Sstevel@tonic-gate 	udp->d_ino	= hdp->ext_lbn;
5987c478bd9Sstevel@tonic-gate 
5997c478bd9Sstevel@tonic-gate 	c = IDE_FLAGS(bufp);
6007c478bd9Sstevel@tonic-gate 	if (IDE_REGULAR_FILE(c)) {
6017c478bd9Sstevel@tonic-gate 		hdp->type = VREG;
6027c478bd9Sstevel@tonic-gate 		hdp->mode = IFREG;
6037c478bd9Sstevel@tonic-gate 		hdp->nlink = 1;
6047c478bd9Sstevel@tonic-gate 	} else if (IDE_REGULAR_DIR(c)) {
6057c478bd9Sstevel@tonic-gate 		hdp->type = VDIR;
6067c478bd9Sstevel@tonic-gate 		hdp->mode = IFDIR;
6077c478bd9Sstevel@tonic-gate 		hdp->nlink = 2;
6087c478bd9Sstevel@tonic-gate 	} else {
6097c478bd9Sstevel@tonic-gate 		printf("pd(): file type=0x%x unknown.\n", c);
6107c478bd9Sstevel@tonic-gate 	}
6117c478bd9Sstevel@tonic-gate 
6127c478bd9Sstevel@tonic-gate 	/*
6137c478bd9Sstevel@tonic-gate 	 * Massage hsfs name, recognizing special entries for . and ..
6147c478bd9Sstevel@tonic-gate 	 * else lopping off version junk.
6157c478bd9Sstevel@tonic-gate 	 */
6167c478bd9Sstevel@tonic-gate 
6177c478bd9Sstevel@tonic-gate 	/* Some initial conditions */
6187c478bd9Sstevel@tonic-gate 	nmlen = IDE_NAME_LEN(bufp);
6197c478bd9Sstevel@tonic-gate 	c = *IDE_NAME(bufp);
6207c478bd9Sstevel@tonic-gate 	/* Special Case: Current Directory */
6217c478bd9Sstevel@tonic-gate 	if (nmlen == 1 && c == '\0') {
6227c478bd9Sstevel@tonic-gate 		udp->d_name[0] = '.';
6237c478bd9Sstevel@tonic-gate 		udp->d_name[1] = '\0';
6247c478bd9Sstevel@tonic-gate 		udp->d_namlen = 1;
6257c478bd9Sstevel@tonic-gate 	/* Special Case: Parent Directory */
6267c478bd9Sstevel@tonic-gate 	} else if (nmlen == 1 && c == '\001') {
6277c478bd9Sstevel@tonic-gate 		udp->d_name[0] = '.';
6287c478bd9Sstevel@tonic-gate 		udp->d_name[1] = '.';
6297c478bd9Sstevel@tonic-gate 		udp->d_name[2] = '\0';
6307c478bd9Sstevel@tonic-gate 		udp->d_namlen = 2;
6317c478bd9Sstevel@tonic-gate 	/* Other file name */
6327c478bd9Sstevel@tonic-gate 	} else {
6337c478bd9Sstevel@tonic-gate 		udp->d_namlen = 0;
6347c478bd9Sstevel@tonic-gate 		for (i = 0; i < nmlen; i++) {
6357c478bd9Sstevel@tonic-gate 			c = *(IDE_name(bufp)+i);
6367c478bd9Sstevel@tonic-gate 			if (c == ';')
6377c478bd9Sstevel@tonic-gate 				break;
6387c478bd9Sstevel@tonic-gate 			else if (c == ' ')
6397c478bd9Sstevel@tonic-gate 				continue;
6407c478bd9Sstevel@tonic-gate 			else
6417c478bd9Sstevel@tonic-gate 				udp->d_name[udp->d_namlen++] = c;
6427c478bd9Sstevel@tonic-gate 		}
6437c478bd9Sstevel@tonic-gate 		udp->d_name[udp->d_namlen] = '\0';
6447c478bd9Sstevel@tonic-gate 	}
6457c478bd9Sstevel@tonic-gate 
6467c478bd9Sstevel@tonic-gate 	/* System Use Fields */
6477c478bd9Sstevel@tonic-gate 	ce_len = IDE_SUA_LEN(bufp);
6487c478bd9Sstevel@tonic-gate 
64930f5cf21Sjg 	if (ce_len == 0)
6507c478bd9Sstevel@tonic-gate 		return (udp->d_reclen);
6517c478bd9Sstevel@tonic-gate 
6527c478bd9Sstevel@tonic-gate 	/* there is an SUA for this dir entry; go parse it */
6537c478bd9Sstevel@tonic-gate 	ce_lbn = parse_susp((char *)IDE_sys_use_area(bufp), &ce_len, hsdep);
6547c478bd9Sstevel@tonic-gate 
6557c478bd9Sstevel@tonic-gate 	if (ce_lbn) {
6567c478bd9Sstevel@tonic-gate 		/*
6577c478bd9Sstevel@tonic-gate 		 * store away current position in dir,
6587c478bd9Sstevel@tonic-gate 		 * as we will be using the iobuf to reading SUA.
6597c478bd9Sstevel@tonic-gate 		 */
6607c478bd9Sstevel@tonic-gate 		daddr_t save_bn = filep->fi_blocknum;
6617c478bd9Sstevel@tonic-gate 		daddr_t save_offset = filep->fi_offset;
6627c478bd9Sstevel@tonic-gate 		caddr_t save_ma = filep->fi_memp;
6637c478bd9Sstevel@tonic-gate 		int save_cc = filep->fi_count;
6647c478bd9Sstevel@tonic-gate 		do {
6657c478bd9Sstevel@tonic-gate 			filep->fi_count = ISO_SECTOR_SIZE;
6667c478bd9Sstevel@tonic-gate 			filep->fi_offset = 0;
6677c478bd9Sstevel@tonic-gate 			filep->fi_blocknum = hdbtodb(ce_lbn);
6687c478bd9Sstevel@tonic-gate 			filep->fi_memp = 0;
6697c478bd9Sstevel@tonic-gate 			if (diskread(filep)) {
6707c478bd9Sstevel@tonic-gate 				printf("failed to read cont. area\n");
6717c478bd9Sstevel@tonic-gate 				ce_len = 0;
6727c478bd9Sstevel@tonic-gate 				ce_lbn = 0;
6737c478bd9Sstevel@tonic-gate 				break;
6747c478bd9Sstevel@tonic-gate 			}
6757c478bd9Sstevel@tonic-gate 			ce_lbn = parse_susp(filep->fi_memp, &ce_len,
6767c478bd9Sstevel@tonic-gate 			    hsdep);
6777c478bd9Sstevel@tonic-gate 		} while (ce_lbn);
6787c478bd9Sstevel@tonic-gate 		filep->fi_count = save_cc;
6797c478bd9Sstevel@tonic-gate 		filep->fi_offset = save_offset;
6807c478bd9Sstevel@tonic-gate 		filep->fi_blocknum = save_bn;
6817c478bd9Sstevel@tonic-gate 		filep->fi_memp = save_ma;
6827c478bd9Sstevel@tonic-gate 	}
6837c478bd9Sstevel@tonic-gate 	return (udp->d_reclen);
6847c478bd9Sstevel@tonic-gate }
6857c478bd9Sstevel@tonic-gate 
6867c478bd9Sstevel@tonic-gate /*
6877c478bd9Sstevel@tonic-gate  * Parse the System Use Fields in this System Use Area.
6887c478bd9Sstevel@tonic-gate  * Return blk number of continuation/SUA, or 0 if no continuation/not a SUA.
6897c478bd9Sstevel@tonic-gate  */
6907c478bd9Sstevel@tonic-gate static uint_t
6917c478bd9Sstevel@tonic-gate parse_susp(char *bufp, uint_t *len, struct hs_direct *hsdep)
6927c478bd9Sstevel@tonic-gate {
6937c478bd9Sstevel@tonic-gate 	struct direct *udp = &hsdep->hs_ufs_dir; /* ufs-style info */
6947c478bd9Sstevel@tonic-gate 	char *susp;
6957c478bd9Sstevel@tonic-gate 	uint_t cur_off = 0;
6967c478bd9Sstevel@tonic-gate 	uint_t blk_len = *len;
6977c478bd9Sstevel@tonic-gate 	uint_t susp_len = 0;
6987c478bd9Sstevel@tonic-gate 	uint_t ce_lbn = 0;
6997c478bd9Sstevel@tonic-gate 	uint_t i;
7007c478bd9Sstevel@tonic-gate 
7017c478bd9Sstevel@tonic-gate 	dprintf("parse_susp: len = %d\n", *len);
7027c478bd9Sstevel@tonic-gate 	while (cur_off < blk_len) {
7037c478bd9Sstevel@tonic-gate 		susp = (char *)(bufp + cur_off);
7047c478bd9Sstevel@tonic-gate 
7057c478bd9Sstevel@tonic-gate 		/*
7067c478bd9Sstevel@tonic-gate 		 * A null entry, or an entry with zero length
7077c478bd9Sstevel@tonic-gate 		 * terminates the SUSP.
7087c478bd9Sstevel@tonic-gate 		 */
7097c478bd9Sstevel@tonic-gate 		if (susp[0] == '\0' || susp[1] == '\0' ||
7107c478bd9Sstevel@tonic-gate 		    (susp_len = SUF_LEN(susp)) == 0)
7117c478bd9Sstevel@tonic-gate 			break;
7127c478bd9Sstevel@tonic-gate 
7137c478bd9Sstevel@tonic-gate 		/*
7147c478bd9Sstevel@tonic-gate 		 * Compare current entry to all known signatures.
7157c478bd9Sstevel@tonic-gate 		 */
7167c478bd9Sstevel@tonic-gate 		for (i = 0; i < hsfs_num_sig; i++)
7177c478bd9Sstevel@tonic-gate 			if (strncmp(hsfs_sig_tab[i], susp, SUF_SIG_LEN) == 0)
7187c478bd9Sstevel@tonic-gate 				break;
7197c478bd9Sstevel@tonic-gate 		switch (i) {
7207c478bd9Sstevel@tonic-gate 		case SUSP_CE_IX:
7217c478bd9Sstevel@tonic-gate 			/*
7227c478bd9Sstevel@tonic-gate 			 * CE signature: continuation of SUSP.
7237c478bd9Sstevel@tonic-gate 			 * will want to return new lbn, len.
7247c478bd9Sstevel@tonic-gate 			 */
7257c478bd9Sstevel@tonic-gate 			ce_lbn = CE_BLK_LOC(susp);
7267c478bd9Sstevel@tonic-gate 			*len = CE_CONT_LEN(susp);
7277c478bd9Sstevel@tonic-gate 			break;
7287c478bd9Sstevel@tonic-gate 		case RRIP_NM_IX:
7297c478bd9Sstevel@tonic-gate 			/* NM signature: POSIX-style file name */
7307c478bd9Sstevel@tonic-gate 			if (!RRIP_NAME_FLAGS(susp)) {
7317c478bd9Sstevel@tonic-gate 				udp->d_namlen = RRIP_NAME_LEN(susp);
7327c478bd9Sstevel@tonic-gate 				bcopy((char *)RRIP_name(susp),
7337c478bd9Sstevel@tonic-gate 				    udp->d_name, udp->d_namlen);
7347c478bd9Sstevel@tonic-gate 				udp->d_name[udp->d_namlen] = '\0';
7357c478bd9Sstevel@tonic-gate 			}
7367c478bd9Sstevel@tonic-gate 			break;
7377c478bd9Sstevel@tonic-gate 		case HSFS_NUM_SIG:
7387c478bd9Sstevel@tonic-gate 			/* couldn't find a legit susp, terminate loop */
7397c478bd9Sstevel@tonic-gate 		case SUSP_ST_IX:
7407c478bd9Sstevel@tonic-gate 			/* ST signature: terminates SUSP */
7417c478bd9Sstevel@tonic-gate 			return (ce_lbn);
7427c478bd9Sstevel@tonic-gate 		case SUSP_SP_IX:
7437c478bd9Sstevel@tonic-gate 		case RRIP_RR_IX:
7447c478bd9Sstevel@tonic-gate 		default:
7457c478bd9Sstevel@tonic-gate 			break;
7467c478bd9Sstevel@tonic-gate 		}
7477c478bd9Sstevel@tonic-gate 		cur_off += susp_len;
7487c478bd9Sstevel@tonic-gate 	}
7497c478bd9Sstevel@tonic-gate 	return (ce_lbn);
7507c478bd9Sstevel@tonic-gate }
7517c478bd9Sstevel@tonic-gate 
7527c478bd9Sstevel@tonic-gate struct boot_fs_ops bhsfs_ops = {
7537c478bd9Sstevel@tonic-gate 	"boot_hsfs",
7547c478bd9Sstevel@tonic-gate 	bhsfs_mountroot,
7557c478bd9Sstevel@tonic-gate 	bhsfs_unmountroot,
7567c478bd9Sstevel@tonic-gate 	bhsfs_open,
7577c478bd9Sstevel@tonic-gate 	bhsfs_close,
7587c478bd9Sstevel@tonic-gate 	bhsfs_read,
7597c478bd9Sstevel@tonic-gate 	bhsfs_lseek,
7607c478bd9Sstevel@tonic-gate 	NULL
7617c478bd9Sstevel@tonic-gate };
762