1 /* $NetBSD: rawfs.c,v 1.8 2006/01/25 18:28:27 christos Exp $ */ 2 3 /* 4 * Copyright (c) 1995 Gordon W. Ross 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. The name of the author may not be used to endorse or promote products 16 * derived from this software without specific prior written permission. 17 * 4. All advertising materials mentioning features or use of this software 18 * must display the following acknowledgement: 19 * This product includes software developed by Gordon W. Ross 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 /* 34 * Raw file system - for stream devices like tapes. 35 * No random access, only sequential read allowed. 36 * This exists only to allow upper level code to be 37 * shielded from the fact that the device must be 38 * read only with whole block position and size. 39 */ 40 41 #include <sys/param.h> 42 #include <lib/libsa/stand.h> 43 #include <rawfs.h> 44 45 extern int debug; 46 47 #define RAWFS_BSIZE 8192 48 49 /* 50 * In-core open file. 51 */ 52 struct file { 53 daddr_t fs_nextblk; /* block number to read next */ 54 daddr_t fs_curblk; /* block number currently in buffer */ 55 int fs_len; /* amount left in f_buf */ 56 char * fs_ptr; /* read pointer into f_buf */ 57 char fs_buf[RAWFS_BSIZE]; 58 }; 59 60 static int 61 rawfs_get_block __P((struct open_file *)); 62 63 int rawfs_open(path, f) 64 const char *path; 65 struct open_file *f; 66 { 67 struct file *fs; 68 69 /* 70 * The actual PROM driver has already been opened. 71 * Just allocate the I/O buffer, etc. 72 */ 73 fs = alloc(sizeof(struct file)); 74 fs->fs_nextblk = 0; 75 fs->fs_curblk = -1; 76 fs->fs_len = 0; 77 fs->fs_ptr = fs->fs_buf; 78 79 f->f_fsdata = fs; 80 return (0); 81 } 82 83 int rawfs_close(f) 84 struct open_file *f; 85 { 86 struct file *fs; 87 88 fs = (struct file *) f->f_fsdata; 89 f->f_fsdata = (void *)0; 90 91 if (fs != (struct file *)0) 92 dealloc(fs, sizeof(*fs)); 93 94 return (0); 95 } 96 97 int rawfs_read(f, start, size, resid) 98 struct open_file *f; 99 void *start; 100 u_int size; 101 u_int *resid; 102 { 103 struct file *fs = (struct file *)f->f_fsdata; 104 char *addr = start; 105 int error = 0; 106 size_t csize; 107 108 while (size != 0) { 109 110 if (fs->fs_len == 0) 111 if ((error = rawfs_get_block(f)) != 0) 112 break; 113 114 if (fs->fs_len <= 0) 115 break; /* EOF */ 116 117 csize = size; 118 if (csize > fs->fs_len) 119 csize = fs->fs_len; 120 121 memcpy(addr, fs->fs_ptr, csize); 122 fs->fs_ptr += csize; 123 fs->fs_len -= csize; 124 addr += csize; 125 size -= csize; 126 } 127 if (resid) 128 *resid = size; 129 130 if (error) { 131 errno = error; 132 error = -1; 133 } 134 135 return (error); 136 } 137 138 int rawfs_write(f, start, size, resid) 139 struct open_file *f; 140 void *start; 141 size_t size; 142 size_t *resid; /* out */ 143 { 144 errno = EROFS; 145 return (-1); 146 } 147 148 off_t rawfs_seek(f, offset, where) 149 struct open_file *f; 150 off_t offset; 151 int where; 152 { 153 struct file *fs = (struct file *)f->f_fsdata; 154 daddr_t curblk, targblk; 155 off_t newoff; 156 int err, idx; 157 158 /* 159 * We support a very minimal feature set for lseek(2); just 160 * enough to allow loadfile() to work with the parameters 161 * we pass to it on boot. 162 * 163 * In all cases, we can't seek back past the start of the 164 * current block. 165 */ 166 curblk = (fs->fs_curblk < 0) ? 0 : fs->fs_curblk; 167 168 /* 169 * Only support SEEK_SET and SEEK_CUR which result in offsets 170 * which don't require seeking backwards. 171 */ 172 switch (where) { 173 case SEEK_SET: 174 newoff = offset; 175 break; 176 177 case SEEK_CUR: 178 if (fs->fs_curblk < 0) 179 newoff = 0; 180 else { 181 newoff = fs->fs_curblk * RAWFS_BSIZE; 182 newoff += RAWFS_BSIZE - fs->fs_len; 183 } 184 newoff += offset; 185 break; 186 187 default: 188 errno = EINVAL; 189 return (-1); 190 } 191 192 if (newoff < (curblk * RAWFS_BSIZE)) { 193 errno = EINVAL; 194 return (-1); 195 } 196 197 targblk = newoff / RAWFS_BSIZE; 198 199 /* 200 * If necessary, skip blocks until we hit the required target 201 */ 202 err = 0; 203 while (fs->fs_curblk != targblk && (err = rawfs_get_block(f)) == 0) 204 ; 205 206 if (err) { 207 errno = err; 208 return (-1); 209 } 210 211 /* 212 * Update the index within the loaded block 213 */ 214 idx = newoff % RAWFS_BSIZE; 215 fs->fs_len = RAWFS_BSIZE - idx; 216 fs->fs_ptr = &fs->fs_buf[idx]; 217 218 return (newoff); 219 } 220 221 int rawfs_stat(f, sb) 222 struct open_file *f; 223 struct stat *sb; 224 { 225 errno = EFTYPE; 226 return (-1); 227 } 228 229 230 /* 231 * Read a block from the underlying stream device 232 * (In our case, a tape drive.) 233 */ 234 static int 235 rawfs_get_block(f) 236 struct open_file *f; 237 { 238 struct file *fs; 239 int error, len; 240 241 fs = (struct file *)f->f_fsdata; 242 fs->fs_ptr = fs->fs_buf; 243 244 twiddle(); 245 error = f->f_dev->dv_strategy(f->f_devdata, F_READ, 246 fs->fs_nextblk * (RAWFS_BSIZE / DEV_BSIZE), 247 RAWFS_BSIZE, fs->fs_buf, &len); 248 249 if (!error) { 250 fs->fs_len = len; 251 fs->fs_curblk = fs->fs_nextblk; 252 fs->fs_nextblk += 1; 253 } else { 254 errno = error; 255 error = -1; 256 } 257 258 return (error); 259 } 260