1 /* $NetBSD: unixdev.c,v 1.1 2009/03/02 09:33:02 nonaka Exp $ */ 2 /* $OpenBSD: unixdev.c,v 1.6 2007/06/16 00:26:33 deraadt Exp $ */ 3 4 /* 5 * Copyright (c) 1996-1998 Michael Shalayeff 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 * 29 */ 30 31 #include <sys/param.h> 32 #include <sys/reboot.h> 33 34 #include <machine/stdarg.h> 35 36 #include "boot.h" 37 #include "bootinfo.h" 38 #include "disk.h" 39 #include "unixdev.h" 40 #include "compat_linux.h" 41 42 static struct btinfo_bootdisk bi_disk; 43 44 int 45 unixstrategy(void *devdata, int rw, daddr_t blk, size_t size, void *buf, 46 size_t *rsize) 47 { 48 off_t off; 49 int fd = (int)devdata; 50 int rc = 0; 51 52 #ifdef UNIX_DEBUG 53 printf("unixstrategy: %s %d bytes @ %d\n", 54 ((rw == F_READ) ? "reading" : "writing"), (int)size, (int)blk); 55 #endif 56 57 off = (off_t)blk * DEV_BSIZE; 58 if ((rc = ulseek(fd, off, SEEK_SET)) >= 0) 59 rc = (rw == F_READ) ? uread(fd, buf, size) : 60 uwrite(fd, buf, size); 61 62 if (rc >= 0) { 63 *rsize = (size_t)rc; 64 rc = 0; 65 } else 66 rc = errno; 67 return rc; 68 } 69 70 int 71 unixopen(struct open_file *f, ...) 72 { 73 va_list ap; 74 char path[PATH_MAX]; 75 struct diskinfo *dip; 76 char *devname; 77 const char *fname; 78 int dev; 79 u_int unit, partition; 80 int dospart; 81 82 va_start(ap, f); 83 dev = va_arg(ap, int); 84 devname = va_arg(ap, char *); 85 unit = va_arg(ap, u_int); 86 partition = va_arg(ap, u_int); 87 fname = va_arg(ap, char *); 88 va_end(ap); 89 90 f->f_devdata = NULL; 91 92 /* Find device. */ 93 dip = dkdevice(devname, unit); 94 if (dip == NULL) 95 return ENOENT; 96 97 /* Try for disklabel again (might be removable media). */ 98 if (dip->bios_info.flags & BDI_BADLABEL) { 99 const char *st = bios_getdisklabel(&dip->bios_info, 100 &dip->disklabel); 101 #ifdef UNIX_DEBUG 102 if (debug && st) 103 printf("%s\n", st); 104 #endif 105 if (!st) { 106 dip->bios_info.flags &= ~BDI_BADLABEL; 107 dip->bios_info.flags |= BDI_GOODLABEL; 108 } else 109 return ERDLAB; 110 } 111 112 dospart = bios_getdospart(&dip->bios_info); 113 bios_devpath(dip->bios_info.bios_number, dospart, path); 114 f->f_devdata = (void *)uopen(path, LINUX_O_RDONLY); 115 if ((int)f->f_devdata == -1) 116 return errno; 117 118 bi_disk.biosdev = dip->bios_info.bios_number; 119 bi_disk.partition = partition; 120 bi_disk.labelsector = 121 dip->disklabel.d_partitions[partition].p_offset + LABELSECTOR; 122 bi_disk.label.type = dip->disklabel.d_type; 123 memcpy(bi_disk.label.packname, dip->disklabel.d_packname, 16); 124 bi_disk.label.checksum = dip->disklabel.d_checksum; 125 BI_ADD(&bi_disk, BTINFO_BOOTDISK, sizeof(bi_disk)); 126 127 return 0; 128 } 129 130 int 131 unixclose(struct open_file *f) 132 { 133 134 return uclose((int)f->f_devdata); 135 } 136 137 int 138 unixioctl(struct open_file *f, u_long cmd, void *data) 139 { 140 141 return uioctl((int)f->f_devdata, cmd, data); 142 } 143 144 off_t 145 ulseek(int fd, off_t off, int wh) 146 { 147 extern long ulseek32(int, long, int); 148 off_t r; 149 150 /* XXX only SEEK_SET is used, so anything else can fail for now. */ 151 152 if (wh == SEEK_SET) { 153 if (ulseek32(fd, 0, SEEK_SET) != 0) 154 return -1; 155 while (off > OFFT_OFFSET_MAX) { 156 off -= OFFT_OFFSET_MAX; 157 if (ulseek32(fd, OFFT_OFFSET_MAX, SEEK_CUR) < 0 && 158 errno != LINUX_EOVERFLOW) 159 return -1; 160 } 161 r = ulseek32(fd, (long)off, SEEK_CUR); 162 if (r == -1 && errno == LINUX_EOVERFLOW) 163 r = off; 164 } else 165 r = ulseek32(fd, (long)off, wh); 166 167 return r; 168 } 169