1 /* $NetBSD: bootfs.c,v 1.1 2005/12/29 15:20:09 tsutsui Exp $ */ 2 3 /*- 4 * Copyright (c) 2004 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by UCHIYAMA Yasushi. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the NetBSD 21 * Foundation, Inc. and its contributors. 22 * 4. Neither the name of The NetBSD Foundation nor the names of its 23 * contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ 38 39 #include <lib/libsa/stand.h> 40 #include <lib/libkern/libkern.h> 41 42 #include <machine/param.h> 43 #include <machine/bfs.h> 44 #include <machine/sector.h> 45 46 #include "local.h" 47 48 /* System V bfs */ 49 50 FS_DEF(bfs); 51 52 struct fs_ops bfs_ops = { 53 bfs_open, bfs_close, bfs_read, bfs_write, bfs_seek, bfs_stat 54 }; 55 56 struct bfs_file { 57 struct bfs *bfs; 58 int start, end; 59 size_t size; 60 int cur; 61 uint8_t buf[DEV_BSIZE]; 62 }; 63 64 int 65 bfs_open(const char *name, struct open_file *f) 66 { 67 struct bfs_file *file; 68 69 if ((file = alloc(sizeof *file)) == 0) 70 return -1; 71 memset(file, 0, sizeof *file); 72 73 if (bfs_init(&file->bfs) != 0) { 74 free(file, sizeof *file); 75 return -2; 76 } 77 78 if (!bfs_file_lookup(file->bfs, name, &file->start, &file->end, 79 &file->size)) { 80 bfs_fini(file->bfs); 81 free(file, sizeof *file); 82 return -3; 83 } 84 85 printf("%s: %s %d %d %d\n", __FUNCTION__, name, file->start, 86 file->end, file->size); 87 88 f->f_fsdata = file; 89 90 return 0; 91 } 92 93 int 94 bfs_close(struct open_file *f) 95 { 96 struct bfs_file *file = f->f_fsdata; 97 98 bfs_fini(file->bfs); 99 100 return 0; 101 } 102 103 int 104 bfs_read(struct open_file *f, void *buf, size_t size, size_t *resid) 105 { 106 struct bfs_file *file = f->f_fsdata; 107 int n, start, end; 108 uint8_t *p = buf; 109 size_t bufsz = size; 110 int cur = file->cur; 111 112 if (cur + size > file->size) 113 size = file->size - cur; 114 115 start = file->start + (cur >> DEV_BSHIFT); 116 end = file->start + ((cur + size) >> DEV_BSHIFT); 117 118 /* first sector */ 119 if (!sector_read(0, file->buf, start)) 120 return -2; 121 n = TRUNC_SECTOR(cur) + DEV_BSIZE - cur; 122 if (n >= size) { 123 memcpy(p, file->buf + DEV_BSIZE - n, size); 124 goto done; 125 } 126 memcpy(p, file->buf + DEV_BSIZE - n, n); 127 p += n; 128 129 if ((end - start - 1) > 0) { 130 if (!sector_read_n(0, p, start + 1, end - start - 1)) 131 return -2; 132 p += (end - start - 1) * DEV_BSIZE; 133 } 134 135 /* last sector */ 136 if (!sector_read(0, file->buf, end)) 137 return -2; 138 n = cur + size - TRUNC_SECTOR(cur + size); 139 memcpy(p, file->buf, n); 140 141 done: 142 file->cur += size; 143 144 if (resid) 145 *resid = bufsz - size; 146 147 return 0; 148 } 149 150 int 151 bfs_write(struct open_file *f, void *start, size_t size, size_t *resid) 152 { 153 154 return -1; 155 } 156 157 off_t 158 bfs_seek(struct open_file *f, off_t offset, int where) 159 { 160 struct bfs_file *file = f->f_fsdata; 161 int cur; 162 163 switch (where) { 164 case SEEK_SET: 165 cur = offset; 166 break; 167 case SEEK_CUR: 168 cur = file->cur + offset; 169 break; 170 case SEEK_END: 171 cur = file->size + offset; 172 break; 173 default: 174 return EINVAL; 175 } 176 177 if (cur < 0 || cur >= file->size) { 178 return EINVAL; 179 } 180 181 file->cur = cur; 182 183 return (off_t)cur; 184 } 185 186 int 187 bfs_stat(struct open_file *f, struct stat *stat) 188 { 189 struct bfs_file *file = f->f_fsdata; 190 191 stat->st_size = file->size; 192 193 return 0; 194 } 195