Home | History | Annotate | Line # | Download | only in common
      1 /*	$NetBSD: bootfs.c,v 1.5 2019/01/09 03:28:31 christos 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  *
     19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29  * POSSIBILITY OF SUCH DAMAGE.
     30  */
     31 
     32 #include <lib/libsa/stand.h>
     33 #include <lib/libkern/libkern.h>
     34 
     35 #include <sys/param.h>
     36 #include <machine/bfs.h>
     37 #include <machine/sector.h>
     38 
     39 #include "local.h"
     40 
     41 /* System V bfs */
     42 
     43 FS_DEF(bfs);
     44 
     45 struct fs_ops bfs_ops = {
     46 	bfs_open, bfs_close, bfs_read, bfs_write, bfs_seek, bfs_stat
     47 };
     48 
     49 struct bfs_file {
     50 	struct bfs *bfs;
     51 	int start, end;
     52 	size_t size;
     53 	int cur;
     54 	uint8_t buf[DEV_BSIZE];
     55 };
     56 
     57 int
     58 bfs_open(const char *name, struct open_file *f)
     59 {
     60 	struct bfs_file *file;
     61 
     62 	if ((file = alloc(sizeof *file)) == 0)
     63 		return -1;
     64 	memset(file, 0, sizeof *file);
     65 
     66 	if (bfs_init(&file->bfs) != 0) {
     67 		dealloc(file, sizeof *file);
     68 		return -2;
     69 	}
     70 
     71 	if (!bfs_file_lookup(file->bfs, name, &file->start, &file->end,
     72 	    &file->size)) {
     73 		bfs_fini(file->bfs);
     74 		dealloc(file, sizeof *file);
     75 		return -3;
     76 	}
     77 
     78 	printf("%s: %s %d %d %d\n", __func__, name, file->start,
     79 	    file->end, file->size);
     80 
     81 	f->f_fsdata = file;
     82 
     83 	return 0;
     84 }
     85 
     86 int
     87 bfs_close(struct open_file *f)
     88 {
     89 	struct bfs_file *file = f->f_fsdata;
     90 
     91 	bfs_fini(file->bfs);
     92 
     93 	return 0;
     94 }
     95 
     96 int
     97 bfs_read(struct open_file *f, void *buf, size_t size, size_t *resid)
     98 {
     99 	struct bfs_file *file = f->f_fsdata;
    100 	int n, start, end;
    101 	uint8_t *p = buf;
    102 	size_t bufsz = size;
    103 	int cur = file->cur;
    104 
    105 	if (cur + size > file->size)
    106 		size = file->size - cur;
    107 
    108 	start = file->start + (cur >> DEV_BSHIFT);
    109 	end = file->start + ((cur + size) >> DEV_BSHIFT);
    110 
    111 	/* first sector */
    112 	if (!sector_read(0, file->buf, start))
    113 		return -2;
    114 	n = TRUNC_SECTOR(cur) + DEV_BSIZE - cur;
    115 	if (n >= size) {
    116 		memcpy(p, file->buf + DEV_BSIZE - n, size);
    117 		goto done;
    118 	}
    119 	memcpy(p, file->buf + DEV_BSIZE - n, n);
    120 	p += n;
    121 
    122 	if ((end - start - 1) > 0) {
    123 		if (!sector_read_n(0, p, start + 1, end - start - 1))
    124 			return -2;
    125 		p += (end - start - 1) * DEV_BSIZE;
    126 	}
    127 
    128 	/* last sector */
    129 	if (!sector_read(0, file->buf, end))
    130 		return -2;
    131 	n = cur + size - TRUNC_SECTOR(cur + size);
    132 	memcpy(p, file->buf, n);
    133 
    134  done:
    135 	file->cur += size;
    136 
    137 	if (resid)
    138 		*resid = bufsz - size;
    139 
    140 	return 0;
    141 }
    142 
    143 int
    144 bfs_write(struct open_file *f, void *start, size_t size, size_t *resid)
    145 {
    146 
    147 	return -1;
    148 }
    149 
    150 off_t
    151 bfs_seek(struct open_file *f, off_t offset, int where)
    152 {
    153 	struct bfs_file *file = f->f_fsdata;
    154 	int cur;
    155 
    156 	switch (where) {
    157 	case SEEK_SET:
    158 		cur = offset;
    159 		break;
    160 	case SEEK_CUR:
    161 		cur = file->cur + offset;
    162 		break;
    163 	case SEEK_END:
    164 		cur = file->size + offset;
    165 		break;
    166 	default:
    167 		return EINVAL;
    168 	}
    169 
    170 	if (cur  < 0 || cur >= file->size) {
    171 		return EINVAL;
    172 	}
    173 
    174 	file->cur = cur;
    175 
    176 	return (off_t)cur;
    177 }
    178 
    179 int
    180 bfs_stat(struct open_file *f, struct stat *stat)
    181 {
    182 	struct bfs_file *file = f->f_fsdata;
    183 
    184 	stat->st_size = file->size;
    185 
    186 	return 0;
    187 }
    188