The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/rd.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $OpenBSD: rd.c,v 1.14 2022/04/06 18:59:27 naddy Exp $   */
    2 
    3 /*
    4  * Copyright (c) 2011 Matthew Dempsky <matthew@dempsky.org>
    5  *
    6  * Permission to use, copy, modify, and distribute this software for any
    7  * purpose with or without fee is hereby granted, provided that the above
    8  * copyright notice and this permission notice appear in all copies.
    9  *
   10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
   11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
   12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
   13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
   14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
   15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
   16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
   17  */
   18 
   19 #include <sys/param.h>
   20 #include <sys/systm.h>
   21 #include <sys/proc.h>
   22 #include <sys/errno.h>
   23 #include <sys/buf.h>
   24 #include <sys/malloc.h>
   25 #include <sys/ioctl.h>
   26 #include <sys/disklabel.h>
   27 #include <sys/device.h>
   28 #include <sys/disk.h>
   29 #include <sys/stat.h>
   30 #include <sys/fcntl.h>
   31 #include <sys/uio.h>
   32 #include <sys/conf.h>
   33 #include <sys/dkio.h>
   34 #include <sys/vnode.h>
   35 
   36 #ifndef MINIROOTSIZE
   37 #define MINIROOTSIZE 512
   38 #endif
   39 
   40 #define ROOTBYTES (MINIROOTSIZE << DEV_BSHIFT)
   41 
   42 /*
   43  * This array will be patched to contain a file-system image.
   44  * See the program:  src/distrib/common/rdsetroot.c
   45  */
   46 u_int32_t rd_root_size = ROOTBYTES;
   47 char rd_root_image[ROOTBYTES] = "|This is the root ramdisk!\n";
   48 
   49 void    rdattach(int);
   50 int     rd_match(struct device *, void *, void *);
   51 void    rd_attach(struct device *, struct device *, void *);
   52 int     rd_detach(struct device *, int);
   53 
   54 struct rd_softc {
   55         struct device   sc_dev;
   56         struct disk     sc_dk;
   57 };
   58 
   59 const struct cfattach rd_ca = {
   60         sizeof(struct rd_softc),
   61         rd_match,
   62         rd_attach,
   63         rd_detach
   64 };
   65 
   66 struct cfdriver rd_cd = {
   67         NULL,
   68         "rd",
   69         DV_DISK
   70 };
   71 
   72 #define rdlookup(unit)  ((struct rd_softc *)disk_lookup(&rd_cd, (unit)))
   73 
   74 int     rdgetdisklabel(dev_t, struct rd_softc *, struct disklabel *, int);
   75 
   76 void
   77 rdattach(int num)
   78 {
   79         static struct cfdata cf; /* Fake cf. */
   80         struct rd_softc *sc;
   81         int i;
   82 
   83         /* There's only one rd_root_image, so only attach one rd. */
   84         num = 1;
   85 
   86         /* XXX: Fake up more? */
   87         cf.cf_attach = &rd_ca;
   88         cf.cf_driver = &rd_cd;
   89 
   90         rd_cd.cd_ndevs = num;
   91         rd_cd.cd_devs = mallocarray(num, sizeof(void *), M_DEVBUF, M_NOWAIT);
   92         if (rd_cd.cd_devs == NULL)
   93                 panic("rdattach: out of memory");
   94 
   95         for (i = 0; i < num; ++i) {
   96                 /* Allocate the softc and initialize it. */
   97                 sc = malloc(sizeof(*sc), M_DEVBUF, M_NOWAIT|M_ZERO);
   98                 if (sc == NULL)
   99                         panic("rdattach: out of memory");
  100                 sc->sc_dev.dv_class = DV_DISK;
  101                 sc->sc_dev.dv_cfdata = &cf;
  102                 sc->sc_dev.dv_flags = DVF_ACTIVE;
  103                 sc->sc_dev.dv_unit = i;
  104                 if (snprintf(sc->sc_dev.dv_xname, sizeof(sc->sc_dev.dv_xname),
  105                     "rd%d", i) >= sizeof(sc->sc_dev.dv_xname))
  106                         panic("rdattach: device name too long");
  107                 sc->sc_dev.dv_ref = 1;
  108 
  109                 /* Attach it to the device tree. */
  110                 rd_cd.cd_devs[i] = sc;
  111                 TAILQ_INSERT_TAIL(&alldevs, &sc->sc_dev, dv_list);
  112                 device_ref(&sc->sc_dev);
  113 
  114                 /* Finish initializing. */
  115                 rd_attach(NULL, &sc->sc_dev, NULL);
  116         }
  117 }
  118 
  119 int
  120 rd_match(struct device *parent, void *match, void *aux)
  121 {
  122         return (0);
  123 }
  124 
  125 void
  126 rd_attach(struct device *parent, struct device *self, void *aux)
  127 {
  128         struct rd_softc *sc = (struct rd_softc *)self;
  129 
  130         /* Attach disk. */
  131         sc->sc_dk.dk_name = sc->sc_dev.dv_xname;
  132         disk_attach(&sc->sc_dev, &sc->sc_dk);
  133 }
  134 
  135 int
  136 rd_detach(struct device *self, int flags)
  137 {
  138         struct rd_softc *sc = (struct rd_softc *)self;
  139 
  140         disk_gone(rdopen, self->dv_unit);
  141 
  142         /* Detach disk. */
  143         disk_detach(&sc->sc_dk);
  144 
  145         return (0);
  146 }
  147 
  148 int
  149 rdopen(dev_t dev, int flag, int fmt, struct proc *p)
  150 {
  151         struct rd_softc *sc;
  152         u_int unit, part;
  153         int error;
  154 
  155         unit = DISKUNIT(dev);
  156         part = DISKPART(dev);
  157 
  158         sc = rdlookup(unit);
  159         if (sc == NULL)
  160                 return (ENXIO);
  161 
  162         if ((error = disk_lock(&sc->sc_dk)) != 0)
  163                 goto unref;
  164 
  165         if (sc->sc_dk.dk_openmask == 0) {
  166                 /* Load the partition info if not already loaded. */
  167                 if ((error = rdgetdisklabel(dev, sc, sc->sc_dk.dk_label, 0))
  168                     != 0)
  169                         goto unlock;
  170         }
  171 
  172         error = disk_openpart(&sc->sc_dk, part, fmt, 1);
  173 
  174  unlock:
  175         disk_unlock(&sc->sc_dk);
  176  unref:
  177         device_unref(&sc->sc_dev);
  178         return (error);
  179 }
  180 
  181 int
  182 rdclose(dev_t dev, int flag, int fmt, struct proc *p)
  183 {
  184         struct rd_softc *sc;
  185         u_int unit, part;
  186 
  187         unit = DISKUNIT(dev);
  188         part = DISKPART(dev);
  189 
  190         sc = rdlookup(unit);
  191         if (sc == NULL)
  192                 return (ENXIO);
  193 
  194         disk_lock_nointr(&sc->sc_dk);
  195 
  196         disk_closepart(&sc->sc_dk, part, fmt);
  197 
  198         disk_unlock(&sc->sc_dk);
  199         device_unref(&sc->sc_dev);
  200         return (0);
  201 }
  202 
  203 void
  204 rdstrategy(struct buf *bp)
  205 {
  206         struct rd_softc *sc;
  207         struct partition *p;
  208         size_t off, xfer;
  209         caddr_t addr;
  210         int s;
  211 
  212         sc = rdlookup(DISKUNIT(bp->b_dev));
  213         if (sc == NULL) {
  214                 bp->b_error = ENXIO;
  215                 goto bad;
  216         }
  217 
  218         /* Validate the request. */
  219         if (bounds_check_with_label(bp, sc->sc_dk.dk_label) == -1)
  220                 goto done;
  221 
  222         /* Do the transfer. */
  223         /* XXX: Worry about overflow when computing off? */
  224 
  225         p = &sc->sc_dk.dk_label->d_partitions[DISKPART(bp->b_dev)];
  226         off = DL_GETPOFFSET(p) * sc->sc_dk.dk_label->d_secsize +
  227             (u_int64_t)bp->b_blkno * DEV_BSIZE;
  228         if (off > rd_root_size)
  229                 off = rd_root_size;
  230         xfer = bp->b_bcount;
  231         if (xfer > rd_root_size - off)
  232                 xfer = rd_root_size - off;
  233         addr = rd_root_image + off;
  234         if (bp->b_flags & B_READ)
  235                 memcpy(bp->b_data, addr, xfer);
  236         else
  237                 memcpy(addr, bp->b_data, xfer);
  238         bp->b_resid = bp->b_bcount - xfer;
  239         goto done;
  240 
  241  bad:
  242         bp->b_flags |= B_ERROR;
  243         bp->b_resid = bp->b_bcount;
  244  done:
  245         s = splbio();
  246         biodone(bp);
  247         splx(s);
  248         if (sc != NULL)
  249                 device_unref(&sc->sc_dev);
  250 }
  251 
  252 int
  253 rdioctl(dev_t dev, u_long cmd, caddr_t data, int fflag, struct proc *p)
  254 {
  255         struct rd_softc *sc;
  256         struct disklabel *lp;
  257         int error = 0;
  258 
  259         sc = rdlookup(DISKUNIT(dev));
  260         if (sc == NULL)
  261                 return (ENXIO);
  262 
  263         switch (cmd) {
  264         case DIOCRLDINFO:
  265                 lp = malloc(sizeof(*lp), M_TEMP, M_WAITOK);
  266                 rdgetdisklabel(dev, sc, lp, 0);
  267                 memcpy(sc->sc_dk.dk_label, lp, sizeof(*lp));
  268                 free(lp, M_TEMP, sizeof(*lp));
  269                 goto done;
  270 
  271         case DIOCGPDINFO:
  272                 rdgetdisklabel(dev, sc, (struct disklabel *)data, 1);
  273                 goto done;
  274 
  275         case DIOCGDINFO:
  276                 *(struct disklabel *)data = *(sc->sc_dk.dk_label);
  277                 goto done;
  278 
  279         case DIOCGPART:
  280                 ((struct partinfo *)data)->disklab = sc->sc_dk.dk_label;
  281                 ((struct partinfo *)data)->part =
  282                     &sc->sc_dk.dk_label->d_partitions[DISKPART(dev)];
  283                 goto done;
  284 
  285         case DIOCWDINFO:
  286         case DIOCSDINFO:
  287                 if ((fflag & FWRITE) == 0) {
  288                         error = EBADF;
  289                         goto done;
  290                 }
  291 
  292                 if ((error = disk_lock(&sc->sc_dk)) != 0)
  293                         goto done;
  294 
  295                 error = setdisklabel(sc->sc_dk.dk_label,
  296                     (struct disklabel *)data, sc->sc_dk.dk_openmask);
  297                 if (error == 0) {
  298                         if (cmd == DIOCWDINFO)
  299                                 error = writedisklabel(DISKLABELDEV(dev),
  300                                     rdstrategy, sc->sc_dk.dk_label);
  301                 }
  302 
  303                 disk_unlock(&sc->sc_dk);
  304                 goto done;
  305         }
  306 
  307  done:
  308         device_unref(&sc->sc_dev);
  309         return (error);
  310 }
  311 
  312 int
  313 rdgetdisklabel(dev_t dev, struct rd_softc *sc, struct disklabel *lp,
  314     int spoofonly)
  315 {
  316         bzero(lp, sizeof(struct disklabel));
  317 
  318         lp->d_secsize = DEV_BSIZE;
  319         lp->d_ntracks = 1;
  320         lp->d_nsectors = rd_root_size >> DEV_BSHIFT;
  321         lp->d_ncylinders = 1;
  322         lp->d_secpercyl = lp->d_nsectors;
  323         if (lp->d_secpercyl == 0) {
  324                 lp->d_secpercyl = 100;
  325                 /* as long as it's not 0 - readdisklabel divides by it */
  326         }
  327 
  328         strncpy(lp->d_typename, "RAM disk", sizeof(lp->d_typename));
  329         lp->d_type = DTYPE_SCSI;
  330         strncpy(lp->d_packname, "fictitious", sizeof(lp->d_packname));
  331         DL_SETDSIZE(lp, lp->d_nsectors);
  332         lp->d_version = 1;
  333 
  334         lp->d_magic = DISKMAGIC;
  335         lp->d_magic2 = DISKMAGIC;
  336         lp->d_checksum = dkcksum(lp);
  337 
  338         /* Call the generic disklabel extraction routine. */
  339         return (readdisklabel(DISKLABELDEV(dev), rdstrategy, lp, spoofonly));
  340 }
  341 
  342 int
  343 rdread(dev_t dev, struct uio *uio, int ioflag)
  344 {
  345         return (physio(rdstrategy, dev, B_READ, minphys, uio));
  346 }
  347 
  348 int
  349 rdwrite(dev_t dev, struct uio *uio, int ioflag)
  350 {
  351         return (physio(rdstrategy, dev, B_WRITE, minphys, uio));
  352 }
  353 
  354 int
  355 rddump(dev_t dev, daddr_t blkno, caddr_t va, size_t size)
  356 {
  357         return (ENXIO);
  358 }
  359 
  360 daddr_t
  361 rdsize(dev_t dev)
  362 {
  363         return (-1);
  364 }

Cache object: 4e29ec931cc3ab85063bfa56107bf516


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.