1f6011da8SMark Murray /*- 2f6011da8SMark Murray * Copyright (c) 2000 Mark R. V. Murray & Jeroen C. van Gelderen 344562634SMark Murray * Copyright (c) 2001-2004 Mark R. V. Murray 4*a345aa59SEitan Adler * Copyright (c) 2014 Eitan Adler 5f6011da8SMark Murray * All rights reserved. 6f6011da8SMark Murray * 7f6011da8SMark Murray * Redistribution and use in source and binary forms, with or without 8f6011da8SMark Murray * modification, are permitted provided that the following conditions 9f6011da8SMark Murray * are met: 10f6011da8SMark Murray * 1. Redistributions of source code must retain the above copyright 11f6011da8SMark Murray * notice, this list of conditions and the following disclaimer 12f6011da8SMark Murray * in this position and unchanged. 13f6011da8SMark Murray * 2. Redistributions in binary form must reproduce the above copyright 14f6011da8SMark Murray * notice, this list of conditions and the following disclaimer in the 15f6011da8SMark Murray * documentation and/or other materials provided with the distribution. 16f6011da8SMark Murray * 17f6011da8SMark Murray * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR 18f6011da8SMark Murray * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19f6011da8SMark Murray * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20f6011da8SMark Murray * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21f6011da8SMark Murray * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22f6011da8SMark Murray * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23f6011da8SMark Murray * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24f6011da8SMark Murray * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25f6011da8SMark Murray * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26f6011da8SMark Murray * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27f6011da8SMark Murray * 28f6011da8SMark Murray */ 29f6011da8SMark Murray 30aad970f1SDavid E. O'Brien #include <sys/cdefs.h> 31aad970f1SDavid E. O'Brien __FBSDID("$FreeBSD$"); 32aad970f1SDavid E. O'Brien 33f6011da8SMark Murray #include <sys/param.h> 34f6011da8SMark Murray #include <sys/systm.h> 35f6011da8SMark Murray #include <sys/conf.h> 36f6011da8SMark Murray #include <sys/uio.h> 37f6011da8SMark Murray #include <sys/kernel.h> 38f6011da8SMark Murray #include <sys/malloc.h> 39f6011da8SMark Murray #include <sys/module.h> 40acd3428bSRobert Watson #include <sys/priv.h> 412dd527b3SPoul-Henning Kamp #include <sys/disk.h> 42f6011da8SMark Murray #include <sys/bus.h> 43844d43d9SGeorge V. Neville-Neil #include <sys/filio.h> 44cfb00e5aSMatthew D Fleming 45f6011da8SMark Murray #include <machine/bus.h> 46cfb00e5aSMatthew D Fleming #include <machine/vmparam.h> 47f6011da8SMark Murray 48f6011da8SMark Murray /* For use with destroy_dev(9). */ 4989c9c53dSPoul-Henning Kamp static struct cdev *null_dev; 5089c9c53dSPoul-Henning Kamp static struct cdev *zero_dev; 51*a345aa59SEitan Adler static struct cdev *full_dev; 52f6011da8SMark Murray 53*a345aa59SEitan Adler static d_write_t full_write; 5411197ed1SMark Murray static d_write_t null_write; 5581661c94SPoul-Henning Kamp static d_ioctl_t null_ioctl; 56844d43d9SGeorge V. Neville-Neil static d_ioctl_t zero_ioctl; 5711197ed1SMark Murray static d_read_t zero_read; 58f6011da8SMark Murray 59f6011da8SMark Murray static struct cdevsw null_cdevsw = { 60dc08ffecSPoul-Henning Kamp .d_version = D_VERSION, 614e0a104fSMark Murray .d_read = (d_read_t *)nullop, 627ac40f5fSPoul-Henning Kamp .d_write = null_write, 637ac40f5fSPoul-Henning Kamp .d_ioctl = null_ioctl, 647ac40f5fSPoul-Henning Kamp .d_name = "null", 65f6011da8SMark Murray }; 66f6011da8SMark Murray 67f6011da8SMark Murray static struct cdevsw zero_cdevsw = { 68dc08ffecSPoul-Henning Kamp .d_version = D_VERSION, 697ac40f5fSPoul-Henning Kamp .d_read = zero_read, 707ac40f5fSPoul-Henning Kamp .d_write = null_write, 71844d43d9SGeorge V. Neville-Neil .d_ioctl = zero_ioctl, 727ac40f5fSPoul-Henning Kamp .d_name = "zero", 73dc08ffecSPoul-Henning Kamp .d_flags = D_MMAP_ANON, 74f6011da8SMark Murray }; 75f6011da8SMark Murray 76*a345aa59SEitan Adler static struct cdevsw full_cdevsw = { 77*a345aa59SEitan Adler .d_version = D_VERSION, 78*a345aa59SEitan Adler .d_read = zero_read, 79*a345aa59SEitan Adler .d_write = full_write, 80*a345aa59SEitan Adler .d_ioctl = zero_ioctl, 81*a345aa59SEitan Adler .d_name = "full", 82*a345aa59SEitan Adler }; 83*a345aa59SEitan Adler 84*a345aa59SEitan Adler 85*a345aa59SEitan Adler /* ARGSUSED */ 86*a345aa59SEitan Adler static int 87*a345aa59SEitan Adler full_write(struct cdev *dev __unused, struct uio *uio, int flags __unused) 88*a345aa59SEitan Adler { 89*a345aa59SEitan Adler 90*a345aa59SEitan Adler return (ENOSPC); 91*a345aa59SEitan Adler } 92*a345aa59SEitan Adler 938f559ca0SMark Murray /* ARGSUSED */ 94a36ef7f3SPoul-Henning Kamp static int 9589c9c53dSPoul-Henning Kamp null_write(struct cdev *dev __unused, struct uio *uio, int flags __unused) 96f6011da8SMark Murray { 97f6011da8SMark Murray uio->uio_resid = 0; 9844562634SMark Murray 9944562634SMark Murray return (0); 100f6011da8SMark Murray } 101f6011da8SMark Murray 1028f559ca0SMark Murray /* ARGSUSED */ 103f6011da8SMark Murray static int 10489c9c53dSPoul-Henning Kamp null_ioctl(struct cdev *dev __unused, u_long cmd, caddr_t data __unused, 1058f559ca0SMark Murray int flags __unused, struct thread *td) 10681661c94SPoul-Henning Kamp { 10781661c94SPoul-Henning Kamp int error; 108844d43d9SGeorge V. Neville-Neil error = 0; 10981661c94SPoul-Henning Kamp 110844d43d9SGeorge V. Neville-Neil switch (cmd) { 111844d43d9SGeorge V. Neville-Neil case DIOCSKERNELDUMP: 112acd3428bSRobert Watson error = priv_check(td, PRIV_SETDUMPER); 113844d43d9SGeorge V. Neville-Neil if (error == 0) 114bad7e7f3SAlfred Perlstein error = set_dumper(NULL, NULL); 115844d43d9SGeorge V. Neville-Neil break; 116844d43d9SGeorge V. Neville-Neil case FIONBIO: 117844d43d9SGeorge V. Neville-Neil break; 118844d43d9SGeorge V. Neville-Neil case FIOASYNC: 119844d43d9SGeorge V. Neville-Neil if (*(int *)data != 0) 120844d43d9SGeorge V. Neville-Neil error = EINVAL; 121844d43d9SGeorge V. Neville-Neil break; 122844d43d9SGeorge V. Neville-Neil default: 123844d43d9SGeorge V. Neville-Neil error = ENOIOCTL; 12481661c94SPoul-Henning Kamp } 125844d43d9SGeorge V. Neville-Neil return (error); 126844d43d9SGeorge V. Neville-Neil } 127844d43d9SGeorge V. Neville-Neil 128844d43d9SGeorge V. Neville-Neil /* ARGSUSED */ 129844d43d9SGeorge V. Neville-Neil static int 130844d43d9SGeorge V. Neville-Neil zero_ioctl(struct cdev *dev __unused, u_long cmd, caddr_t data __unused, 131844d43d9SGeorge V. Neville-Neil int flags __unused, struct thread *td) 132844d43d9SGeorge V. Neville-Neil { 133844d43d9SGeorge V. Neville-Neil int error; 134844d43d9SGeorge V. Neville-Neil error = 0; 135844d43d9SGeorge V. Neville-Neil 136844d43d9SGeorge V. Neville-Neil switch (cmd) { 137844d43d9SGeorge V. Neville-Neil case FIONBIO: 138844d43d9SGeorge V. Neville-Neil break; 139844d43d9SGeorge V. Neville-Neil case FIOASYNC: 140844d43d9SGeorge V. Neville-Neil if (*(int *)data != 0) 141844d43d9SGeorge V. Neville-Neil error = EINVAL; 142844d43d9SGeorge V. Neville-Neil break; 143844d43d9SGeorge V. Neville-Neil default: 144844d43d9SGeorge V. Neville-Neil error = ENOIOCTL; 145844d43d9SGeorge V. Neville-Neil } 146844d43d9SGeorge V. Neville-Neil return (error); 147844d43d9SGeorge V. Neville-Neil } 148844d43d9SGeorge V. Neville-Neil 14981661c94SPoul-Henning Kamp 150ef8b020cSMark Murray /* ARGSUSED */ 15181661c94SPoul-Henning Kamp static int 15289c9c53dSPoul-Henning Kamp zero_read(struct cdev *dev __unused, struct uio *uio, int flags __unused) 153f6011da8SMark Murray { 15489cb2a19SMatthew D Fleming void *zbuf; 15589cb2a19SMatthew D Fleming ssize_t len; 156f6011da8SMark Murray int error = 0; 157f6011da8SMark Murray 15889cb2a19SMatthew D Fleming KASSERT(uio->uio_rw == UIO_READ, 15989cb2a19SMatthew D Fleming ("Can't be in %s for write", __func__)); 16089cb2a19SMatthew D Fleming zbuf = __DECONST(void *, zero_region); 16189cb2a19SMatthew D Fleming while (uio->uio_resid > 0 && error == 0) { 16289cb2a19SMatthew D Fleming len = uio->uio_resid; 16389cb2a19SMatthew D Fleming if (len > ZERO_REGION_SIZE) 16489cb2a19SMatthew D Fleming len = ZERO_REGION_SIZE; 16589cb2a19SMatthew D Fleming error = uiomove(zbuf, len, uio); 16689cb2a19SMatthew D Fleming } 16744562634SMark Murray 16844562634SMark Murray return (error); 169f6011da8SMark Murray } 170f6011da8SMark Murray 171ef8b020cSMark Murray /* ARGSUSED */ 172f6011da8SMark Murray static int 173ef8b020cSMark Murray null_modevent(module_t mod __unused, int type, void *data __unused) 174f6011da8SMark Murray { 175f6011da8SMark Murray switch(type) { 176f6011da8SMark Murray case MOD_LOAD: 177f6011da8SMark Murray if (bootverbose) 178*a345aa59SEitan Adler printf("null: <full device, null device, zero device>\n"); 179*a345aa59SEitan Adler full_dev = make_dev_credf(MAKEDEV_ETERNAL_KLD, &full_cdevsw, 0, 180*a345aa59SEitan Adler NULL, UID_ROOT, GID_WHEEL, 0666, "full"); 181f53444bcSKonstantin Belousov null_dev = make_dev_credf(MAKEDEV_ETERNAL_KLD, &null_cdevsw, 0, 182f53444bcSKonstantin Belousov NULL, UID_ROOT, GID_WHEEL, 0666, "null"); 183f53444bcSKonstantin Belousov zero_dev = make_dev_credf(MAKEDEV_ETERNAL_KLD, &zero_cdevsw, 0, 184f53444bcSKonstantin Belousov NULL, UID_ROOT, GID_WHEEL, 0666, "zero"); 18544562634SMark Murray break; 186f6011da8SMark Murray 187f6011da8SMark Murray case MOD_UNLOAD: 188*a345aa59SEitan Adler destroy_dev(full_dev); 189f6011da8SMark Murray destroy_dev(null_dev); 190f6011da8SMark Murray destroy_dev(zero_dev); 19144562634SMark Murray break; 192f6011da8SMark Murray 193f6011da8SMark Murray case MOD_SHUTDOWN: 19444562634SMark Murray break; 195f6011da8SMark Murray 1963e019deaSPoul-Henning Kamp default: 1973e019deaSPoul-Henning Kamp return (EOPNOTSUPP); 198f6011da8SMark Murray } 19944562634SMark Murray 20044562634SMark Murray return (0); 201f6011da8SMark Murray } 202f6011da8SMark Murray 203005b841fSJohn Baldwin DEV_MODULE(null, null_modevent, NULL); 2044ec450ceSMark Murray MODULE_VERSION(null, 1); 205