cgd.c revision 1.114.4.7 1 /* $NetBSD: cgd.c,v 1.114.4.7 2017/05/17 01:44:17 pgoyette Exp $ */
2
3 /*-
4 * Copyright (c) 2002 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Roland C. Dowdeswell.
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 <sys/cdefs.h>
33 __KERNEL_RCSID(0, "$NetBSD: cgd.c,v 1.114.4.7 2017/05/17 01:44:17 pgoyette Exp $");
34
35 #include <sys/types.h>
36 #include <sys/param.h>
37 #include <sys/systm.h>
38 #include <sys/proc.h>
39 #include <sys/errno.h>
40 #include <sys/buf.h>
41 #include <sys/bufq.h>
42 #include <sys/malloc.h>
43 #include <sys/module.h>
44 #include <sys/pool.h>
45 #include <sys/ioctl.h>
46 #include <sys/device.h>
47 #include <sys/disk.h>
48 #include <sys/disklabel.h>
49 #include <sys/fcntl.h>
50 #include <sys/namei.h> /* for pathbuf */
51 #include <sys/vnode.h>
52 #include <sys/conf.h>
53 #include <sys/syslog.h>
54
55 #include <dev/dkvar.h>
56 #include <dev/cgdvar.h>
57
58 #include <miscfs/specfs/specdev.h> /* for v_rdev */
59
60 #include "ioconf.h"
61
62 struct selftest_params {
63 const char *alg;
64 int blocksize; /* number of bytes */
65 int secsize;
66 daddr_t blkno;
67 int keylen; /* number of bits */
68 int txtlen; /* number of bytes */
69 const uint8_t *key;
70 const uint8_t *ptxt;
71 const uint8_t *ctxt;
72 };
73
74 /* Entry Point Functions */
75
76 static dev_type_open(cgdopen);
77 static dev_type_close(cgdclose);
78 static dev_type_read(cgdread);
79 static dev_type_write(cgdwrite);
80 static dev_type_ioctl(cgdioctl);
81 static dev_type_strategy(cgdstrategy);
82 static dev_type_dump(cgddump);
83 static dev_type_size(cgdsize);
84
85 const struct bdevsw cgd_bdevsw = {
86 DEVSW_MODULE_INIT
87 .d_open = cgdopen,
88 .d_close = cgdclose,
89 .d_strategy = cgdstrategy,
90 .d_ioctl = cgdioctl,
91 .d_dump = cgddump,
92 .d_psize = cgdsize,
93 .d_discard = nodiscard,
94 .d_flag = D_DISK
95 };
96
97 const struct cdevsw cgd_cdevsw = {
98 DEVSW_MODULE_INIT
99 .d_open = cgdopen,
100 .d_close = cgdclose,
101 .d_read = cgdread,
102 .d_write = cgdwrite,
103 .d_ioctl = cgdioctl,
104 .d_stop = nostop,
105 .d_tty = notty,
106 .d_poll = nopoll,
107 .d_mmap = nommap,
108 .d_kqfilter = nokqfilter,
109 .d_discard = nodiscard,
110 .d_flag = D_DISK
111 };
112
113 /*
114 * Vector 5 from IEEE 1619/D16 truncated to 64 bytes, blkno 1.
115 */
116 static const uint8_t selftest_aes_xts_256_ptxt[64] = {
117 0x27, 0xa7, 0x47, 0x9b, 0xef, 0xa1, 0xd4, 0x76,
118 0x48, 0x9f, 0x30, 0x8c, 0xd4, 0xcf, 0xa6, 0xe2,
119 0xa9, 0x6e, 0x4b, 0xbe, 0x32, 0x08, 0xff, 0x25,
120 0x28, 0x7d, 0xd3, 0x81, 0x96, 0x16, 0xe8, 0x9c,
121 0xc7, 0x8c, 0xf7, 0xf5, 0xe5, 0x43, 0x44, 0x5f,
122 0x83, 0x33, 0xd8, 0xfa, 0x7f, 0x56, 0x00, 0x00,
123 0x05, 0x27, 0x9f, 0xa5, 0xd8, 0xb5, 0xe4, 0xad,
124 0x40, 0xe7, 0x36, 0xdd, 0xb4, 0xd3, 0x54, 0x12,
125 };
126
127 static const uint8_t selftest_aes_xts_256_ctxt[512] = {
128 0x26, 0x4d, 0x3c, 0xa8, 0x51, 0x21, 0x94, 0xfe,
129 0xc3, 0x12, 0xc8, 0xc9, 0x89, 0x1f, 0x27, 0x9f,
130 0xef, 0xdd, 0x60, 0x8d, 0x0c, 0x02, 0x7b, 0x60,
131 0x48, 0x3a, 0x3f, 0xa8, 0x11, 0xd6, 0x5e, 0xe5,
132 0x9d, 0x52, 0xd9, 0xe4, 0x0e, 0xc5, 0x67, 0x2d,
133 0x81, 0x53, 0x2b, 0x38, 0xb6, 0xb0, 0x89, 0xce,
134 0x95, 0x1f, 0x0f, 0x9c, 0x35, 0x59, 0x0b, 0x8b,
135 0x97, 0x8d, 0x17, 0x52, 0x13, 0xf3, 0x29, 0xbb,
136 };
137
138 static const uint8_t selftest_aes_xts_256_key[33] = {
139 0x27, 0x18, 0x28, 0x18, 0x28, 0x45, 0x90, 0x45,
140 0x23, 0x53, 0x60, 0x28, 0x74, 0x71, 0x35, 0x26,
141 0x31, 0x41, 0x59, 0x26, 0x53, 0x58, 0x97, 0x93,
142 0x23, 0x84, 0x62, 0x64, 0x33, 0x83, 0x27, 0x95,
143 0
144 };
145
146 /*
147 * Vector 11 from IEEE 1619/D16 truncated to 64 bytes, blkno 0xffff.
148 */
149 static const uint8_t selftest_aes_xts_512_ptxt[64] = {
150 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
151 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
152 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
153 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
154 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
155 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
156 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
157 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
158 };
159
160 static const uint8_t selftest_aes_xts_512_ctxt[64] = {
161 0x77, 0xa3, 0x12, 0x51, 0x61, 0x8a, 0x15, 0xe6,
162 0xb9, 0x2d, 0x1d, 0x66, 0xdf, 0xfe, 0x7b, 0x50,
163 0xb5, 0x0b, 0xad, 0x55, 0x23, 0x05, 0xba, 0x02,
164 0x17, 0xa6, 0x10, 0x68, 0x8e, 0xff, 0x7e, 0x11,
165 0xe1, 0xd0, 0x22, 0x54, 0x38, 0xe0, 0x93, 0x24,
166 0x2d, 0x6d, 0xb2, 0x74, 0xfd, 0xe8, 0x01, 0xd4,
167 0xca, 0xe0, 0x6f, 0x20, 0x92, 0xc7, 0x28, 0xb2,
168 0x47, 0x85, 0x59, 0xdf, 0x58, 0xe8, 0x37, 0xc2,
169 };
170
171 static const uint8_t selftest_aes_xts_512_key[65] = {
172 0x27, 0x18, 0x28, 0x18, 0x28, 0x45, 0x90, 0x45,
173 0x23, 0x53, 0x60, 0x28, 0x74, 0x71, 0x35, 0x26,
174 0x62, 0x49, 0x77, 0x57, 0x24, 0x70, 0x93, 0x69,
175 0x99, 0x59, 0x57, 0x49, 0x66, 0x96, 0x76, 0x27,
176 0x31, 0x41, 0x59, 0x26, 0x53, 0x58, 0x97, 0x93,
177 0x23, 0x84, 0x62, 0x64, 0x33, 0x83, 0x27, 0x95,
178 0x02, 0x88, 0x41, 0x97, 0x16, 0x93, 0x99, 0x37,
179 0x51, 0x05, 0x82, 0x09, 0x74, 0x94, 0x45, 0x92,
180 0
181 };
182
183 const struct selftest_params selftests[] = {
184 {
185 .alg = "aes-xts",
186 .blocksize = 16,
187 .secsize = 512,
188 .blkno = 1,
189 .keylen = 256,
190 .txtlen = sizeof(selftest_aes_xts_256_ptxt),
191 .key = selftest_aes_xts_256_key,
192 .ptxt = selftest_aes_xts_256_ptxt,
193 .ctxt = selftest_aes_xts_256_ctxt
194 },
195 {
196 .alg = "aes-xts",
197 .blocksize = 16,
198 .secsize = 512,
199 .blkno = 0xffff,
200 .keylen = 512,
201 .txtlen = sizeof(selftest_aes_xts_512_ptxt),
202 .key = selftest_aes_xts_512_key,
203 .ptxt = selftest_aes_xts_512_ptxt,
204 .ctxt = selftest_aes_xts_512_ctxt
205 }
206 };
207
208 static int cgd_match(device_t, cfdata_t, void *);
209 static void cgd_attach(device_t, device_t, void *);
210 static int cgd_detach(device_t, int);
211 static struct cgd_softc *cgd_spawn(int, device_t *);
212 static int cgd_destroy(device_t);
213
214 /* Internal Functions */
215
216 static int cgd_diskstart(device_t, struct buf *);
217 static void cgdiodone(struct buf *);
218 static int cgd_dumpblocks(device_t, void *, daddr_t, int);
219
220 static int cgd_ioctl_set(struct cgd_softc *, void *, struct lwp *);
221 static int cgd_ioctl_clr(struct cgd_softc *, struct lwp *);
222 static int cgd_ioctl_get(dev_t, void *, struct lwp *);
223 static int cgdinit(struct cgd_softc *, const char *, struct vnode *,
224 struct lwp *);
225 static void cgd_cipher(struct cgd_softc *, void *, void *,
226 size_t, daddr_t, size_t, int);
227
228 static struct dkdriver cgddkdriver = {
229 .d_minphys = minphys,
230 .d_open = cgdopen,
231 .d_close = cgdclose,
232 .d_strategy = cgdstrategy,
233 .d_iosize = NULL,
234 .d_diskstart = cgd_diskstart,
235 .d_dumpblocks = cgd_dumpblocks,
236 .d_lastclose = NULL
237 };
238
239 CFATTACH_DECL3_NEW(cgd, sizeof(struct cgd_softc),
240 cgd_match, cgd_attach, cgd_detach, NULL, NULL, NULL, DVF_DETACH_SHUTDOWN);
241 extern struct cfdriver cgd_cd;
242
243 /* DIAGNOSTIC and DEBUG definitions */
244
245 #if defined(CGDDEBUG) && !defined(DEBUG)
246 #define DEBUG
247 #endif
248
249 #ifdef DEBUG
250 int cgddebug = 0;
251
252 #define CGDB_FOLLOW 0x1
253 #define CGDB_IO 0x2
254 #define CGDB_CRYPTO 0x4
255
256 #define IFDEBUG(x,y) if (cgddebug & (x)) y
257 #define DPRINTF(x,y) IFDEBUG(x, printf y)
258 #define DPRINTF_FOLLOW(y) DPRINTF(CGDB_FOLLOW, y)
259
260 static void hexprint(const char *, void *, int);
261
262 #else
263 #define IFDEBUG(x,y)
264 #define DPRINTF(x,y)
265 #define DPRINTF_FOLLOW(y)
266 #endif
267
268 #ifdef DIAGNOSTIC
269 #define DIAGPANIC(x) panic x
270 #define DIAGCONDPANIC(x,y) if (x) panic y
271 #else
272 #define DIAGPANIC(x)
273 #define DIAGCONDPANIC(x,y)
274 #endif
275
276 /* Global variables */
277
278 /* Utility Functions */
279
280 #define CGDUNIT(x) DISKUNIT(x)
281 #define GETCGD_SOFTC(_cs, x, _dv) \
282 if (((_cs) = getcgd_softc(x, &_dv)) == NULL) { \
283 return ENXIO; \
284 }
285
286 /* The code */
287
288 /*
289 * Lookup the device and return it's softc. If the device doesn't
290 * exist, spawn it.
291 *
292 * In either case, the device is "acquired", and must be "released"
293 * by the caller after it is finished with the softc.
294 */
295 static struct cgd_softc *
296 getcgd_softc(dev_t dev, device_t *self)
297 {
298 int unit = CGDUNIT(dev);
299 struct cgd_softc *sc;
300
301 DPRINTF_FOLLOW(("getcgd_softc(0x%"PRIx64"): unit = %d\n", dev, unit));
302
303 *self = device_lookup_acquire(&cgd_cd, unit);
304
305 if (*self == NULL) {
306 sc = cgd_spawn(unit, self);
307 } else {
308 sc = device_private(*self);
309 }
310
311 return sc;
312 }
313
314 static int
315 cgd_match(device_t self, cfdata_t cfdata, void *aux)
316 {
317
318 return 1;
319 }
320
321 static void
322 cgd_attach(device_t parent, device_t self, void *aux)
323 {
324 struct cgd_softc *sc;
325
326 sc = device_private(self);
327
328 mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_BIO);
329 dk_init(&sc->sc_dksc, self, DKTYPE_CGD);
330 disk_init(&sc->sc_dksc.sc_dkdev, sc->sc_dksc.sc_xname, &cgddkdriver);
331
332 if (!pmf_device_register(self, NULL, NULL))
333 aprint_error_dev(self,
334 "unable to register power management hooks\n");
335 }
336
337
338 /*
339 * The caller must hold a reference to the device's localcount.
340 */
341 static int
342 cgd_detach(device_t self, int flags)
343 {
344 int ret;
345 const int pmask = 1 << RAW_PART;
346 struct cgd_softc *sc = device_private(self);
347 struct dk_softc *dksc = &sc->sc_dksc;
348
349 if (DK_BUSY(dksc, pmask))
350 return EBUSY;
351
352 if (DK_ATTACHED(dksc) &&
353 (ret = cgd_ioctl_clr(sc, curlwp)) != 0)
354 return ret;
355
356 disk_destroy(&dksc->sc_dkdev);
357 mutex_destroy(&sc->sc_lock);
358
359 return 0;
360 }
361
362 void
363 cgdattach(int num)
364 {
365 int error;
366
367 error = config_cfattach_attach(cgd_cd.cd_name, &cgd_ca);
368 if (error != 0)
369 aprint_error("%s: unable to register cfattach\n",
370 cgd_cd.cd_name);
371 }
372
373 static struct cgd_softc *
374 cgd_spawn(int unit, device_t *self)
375 {
376 cfdata_t cf;
377 struct cgd_softc *sc;
378
379 cf = malloc(sizeof(*cf), M_DEVBUF, M_WAITOK);
380 cf->cf_name = cgd_cd.cd_name;
381 cf->cf_atname = cgd_cd.cd_name;
382 cf->cf_unit = unit;
383 cf->cf_fstate = FSTATE_STAR;
384
385 if ((*self = config_attach_pseudo(cf)) == NULL)
386 return NULL;
387 else {
388 /*
389 * Note that we return while still holding a reference
390 * to the device!
391 */
392 sc = device_private(*self);
393 return sc;
394 }
395 }
396
397 static int
398 cgd_destroy(device_t dev)
399 {
400 int error;
401 cfdata_t cf;
402
403 cf = device_cfdata(dev);
404 error = config_detach_release(dev, DETACH_QUIET);
405 if (error == 0)
406 free(cf, M_DEVBUF);
407
408 return error;
409 }
410
411 static int
412 cgdopen(dev_t dev, int flags, int fmt, struct lwp *l)
413 {
414 device_t self;
415 int error;
416 struct cgd_softc *cs;
417
418 DPRINTF_FOLLOW(("cgdopen(0x%"PRIx64", %d)\n", dev, flags));
419 GETCGD_SOFTC(cs, dev, self);
420 error = dk_open(&cs->sc_dksc, dev, flags, fmt, l);
421 device_release(self);
422 return error;
423 }
424
425 static int
426 cgdclose(dev_t dev, int flags, int fmt, struct lwp *l)
427 {
428 int error;
429 device_t self;
430 struct cgd_softc *cs;
431 struct dk_softc *dksc;
432
433 DPRINTF_FOLLOW(("cgdclose(0x%"PRIx64", %d)\n", dev, flags));
434 GETCGD_SOFTC(cs, dev, self);
435 dksc = &cs->sc_dksc;
436 if ((error = dk_close(dksc, dev, flags, fmt, l)) != 0) {
437 device_release(self);
438 return error;
439 }
440
441 if (!DK_ATTACHED(dksc)) {
442 if ((error = cgd_destroy(cs->sc_dksc.sc_dev)) != 0) {
443 aprint_error_dev(dksc->sc_dev,
444 "unable to detach instance\n");
445 }
446 return error;
447 }
448
449 /* Unit is still attached - just return */
450 device_release(self);
451 return 0;
452 }
453
454 static void
455 cgdstrategy(struct buf *bp)
456 {
457 device_t self;
458 struct cgd_softc *cs = getcgd_softc(bp->b_dev, &self);
459
460 DPRINTF_FOLLOW(("cgdstrategy(%p): b_bcount = %ld\n", bp,
461 (long)bp->b_bcount));
462
463 if (!cs) {
464 bp->b_error = ENXIO;
465 goto bail;
466 }
467
468 /*
469 * Reject unaligned writes.
470 */
471 if (((uintptr_t)bp->b_data & 3) != 0) {
472 bp->b_error = EINVAL;
473 goto bail;
474 }
475
476 dk_strategy(&cs->sc_dksc, bp);
477 device_release(self);
478 return;
479
480 bail:
481 bp->b_resid = bp->b_bcount;
482 biodone(bp);
483 if (self)
484 device_release(self);
485 return;
486 }
487
488 static int
489 cgdsize(dev_t dev)
490 {
491 int retval;
492 device_t self;
493 struct cgd_softc *cs = getcgd_softc(dev, &self);
494
495 DPRINTF_FOLLOW(("cgdsize(0x%"PRIx64")\n", dev));
496 if (!cs)
497 retval = -1;
498 else
499 retval = dk_size(&cs->sc_dksc, dev);
500
501 device_release(self);
502 return retval;
503 }
504
505 /*
506 * cgd_{get,put}data are functions that deal with getting a buffer
507 * for the new encrypted data. We have a buffer per device so that
508 * we can ensure that we can always have a transaction in flight.
509 * We use this buffer first so that we have one less piece of
510 * malloc'ed data at any given point.
511 */
512
513 static void *
514 cgd_getdata(struct dk_softc *dksc, unsigned long size)
515 {
516 struct cgd_softc *cs = (struct cgd_softc *)dksc;
517 void * data = NULL;
518
519 mutex_enter(&cs->sc_lock);
520 if (cs->sc_data_used == 0) {
521 cs->sc_data_used = 1;
522 data = cs->sc_data;
523 }
524 mutex_exit(&cs->sc_lock);
525
526 if (data)
527 return data;
528
529 return malloc(size, M_DEVBUF, M_NOWAIT);
530 }
531
532 static void
533 cgd_putdata(struct dk_softc *dksc, void *data)
534 {
535 struct cgd_softc *cs = (struct cgd_softc *)dksc;
536
537 if (data == cs->sc_data) {
538 mutex_enter(&cs->sc_lock);
539 cs->sc_data_used = 0;
540 mutex_exit(&cs->sc_lock);
541 } else {
542 free(data, M_DEVBUF);
543 }
544 }
545
546 static int
547 cgd_diskstart(device_t dev, struct buf *bp)
548 {
549 struct cgd_softc *cs = device_private(dev);
550 struct dk_softc *dksc = &cs->sc_dksc;
551 struct disk_geom *dg = &dksc->sc_dkdev.dk_geom;
552 struct buf *nbp;
553 void * addr;
554 void * newaddr;
555 daddr_t bn;
556 struct vnode *vp;
557
558 DPRINTF_FOLLOW(("cgd_diskstart(%p, %p)\n", dksc, bp));
559
560 bn = bp->b_rawblkno;
561
562 /*
563 * We attempt to allocate all of our resources up front, so that
564 * we can fail quickly if they are unavailable.
565 */
566 nbp = getiobuf(cs->sc_tvn, false);
567 if (nbp == NULL)
568 return EAGAIN;
569
570 /*
571 * If we are writing, then we need to encrypt the outgoing
572 * block into a new block of memory.
573 */
574 newaddr = addr = bp->b_data;
575 if ((bp->b_flags & B_READ) == 0) {
576 newaddr = cgd_getdata(dksc, bp->b_bcount);
577 if (!newaddr) {
578 putiobuf(nbp);
579 return EAGAIN;
580 }
581 cgd_cipher(cs, newaddr, addr, bp->b_bcount, bn,
582 dg->dg_secsize, CGD_CIPHER_ENCRYPT);
583 }
584
585 nbp->b_data = newaddr;
586 nbp->b_flags = bp->b_flags;
587 nbp->b_oflags = bp->b_oflags;
588 nbp->b_cflags = bp->b_cflags;
589 nbp->b_iodone = cgdiodone;
590 nbp->b_proc = bp->b_proc;
591 nbp->b_blkno = btodb(bn * dg->dg_secsize);
592 nbp->b_bcount = bp->b_bcount;
593 nbp->b_private = bp;
594
595 BIO_COPYPRIO(nbp, bp);
596
597 if ((nbp->b_flags & B_READ) == 0) {
598 vp = nbp->b_vp;
599 mutex_enter(vp->v_interlock);
600 vp->v_numoutput++;
601 mutex_exit(vp->v_interlock);
602 }
603 VOP_STRATEGY(cs->sc_tvn, nbp);
604
605 return 0;
606 }
607
608 static void
609 cgdiodone(struct buf *nbp)
610 {
611 device_t self;
612 struct buf *obp = nbp->b_private;
613 struct cgd_softc *cs = getcgd_softc(obp->b_dev, &self);
614 struct dk_softc *dksc = &cs->sc_dksc;
615 struct disk_geom *dg = &dksc->sc_dkdev.dk_geom;
616 daddr_t bn;
617
618 KDASSERT(cs);
619
620 DPRINTF_FOLLOW(("cgdiodone(%p)\n", nbp));
621 DPRINTF(CGDB_IO, ("cgdiodone: bp %p bcount %d resid %d\n",
622 obp, obp->b_bcount, obp->b_resid));
623 DPRINTF(CGDB_IO, (" dev 0x%"PRIx64", nbp %p bn %" PRId64
624 " addr %p bcnt %d\n", nbp->b_dev, nbp, nbp->b_blkno, nbp->b_data,
625 nbp->b_bcount));
626 if (nbp->b_error != 0) {
627 obp->b_error = nbp->b_error;
628 DPRINTF(CGDB_IO, ("%s: error %d\n", dksc->sc_xname,
629 obp->b_error));
630 }
631
632 /* Perform the decryption if we are reading.
633 *
634 * Note: use the blocknumber from nbp, since it is what
635 * we used to encrypt the blocks.
636 */
637
638 if (nbp->b_flags & B_READ) {
639 bn = dbtob(nbp->b_blkno) / dg->dg_secsize;
640 cgd_cipher(cs, obp->b_data, obp->b_data, obp->b_bcount,
641 bn, dg->dg_secsize, CGD_CIPHER_DECRYPT);
642 }
643
644 /* If we allocated memory, free it now... */
645 if (nbp->b_data != obp->b_data)
646 cgd_putdata(dksc, nbp->b_data);
647
648 putiobuf(nbp);
649
650 /* Request is complete for whatever reason */
651 obp->b_resid = 0;
652 if (obp->b_error != 0)
653 obp->b_resid = obp->b_bcount;
654
655 dk_done(dksc, obp);
656 device_release(self);
657
658 dk_start(dksc, NULL);
659 }
660
661 static int
662 cgd_dumpblocks(device_t dev, void *va, daddr_t blkno, int nblk)
663 {
664 struct cgd_softc *sc = device_private(dev);
665 struct dk_softc *dksc = &sc->sc_dksc;
666 struct disk_geom *dg = &dksc->sc_dkdev.dk_geom;
667 size_t nbytes, blksize;
668 void *buf;
669 int error;
670
671 /*
672 * dk_dump gives us units of disklabel sectors. Everything
673 * else in cgd uses units of diskgeom sectors. These had
674 * better agree; otherwise we need to figure out how to convert
675 * between them.
676 */
677 KASSERTMSG((dg->dg_secsize == dksc->sc_dkdev.dk_label->d_secsize),
678 "diskgeom secsize %"PRIu32" != disklabel secsize %"PRIu32,
679 dg->dg_secsize, dksc->sc_dkdev.dk_label->d_secsize);
680 blksize = dg->dg_secsize;
681
682 /*
683 * Compute the number of bytes in this request, which dk_dump
684 * has `helpfully' converted to a number of blocks for us.
685 */
686 nbytes = nblk*blksize;
687
688 /* Try to acquire a buffer to store the ciphertext. */
689 buf = cgd_getdata(dksc, nbytes);
690 if (buf == NULL)
691 /* Out of memory: give up. */
692 return ENOMEM;
693
694 /* Encrypt the caller's data into the temporary buffer. */
695 cgd_cipher(sc, buf, va, nbytes, blkno, blksize, CGD_CIPHER_ENCRYPT);
696
697 /* Pass it on to the underlying disk device. */
698 error = bdev_dump(sc->sc_tdev, blkno, buf, nbytes);
699
700 /* Release the buffer. */
701 cgd_putdata(dksc, buf);
702
703 /* Return any error from the underlying disk device. */
704 return error;
705 }
706
707 /* XXX: we should probably put these into dksubr.c, mostly */
708 static int
709 cgdread(dev_t dev, struct uio *uio, int flags)
710 {
711 device_t self;
712 int error;
713 struct cgd_softc *cs;
714 struct dk_softc *dksc;
715
716 DPRINTF_FOLLOW(("cgdread(0x%llx, %p, %d)\n",
717 (unsigned long long)dev, uio, flags));
718 GETCGD_SOFTC(cs, dev, self);
719 dksc = &cs->sc_dksc;
720 if (!DK_ATTACHED(dksc)) {
721 device_release(self);
722 return ENXIO;
723 }
724 error = physio(cgdstrategy, NULL, dev, B_READ, minphys, uio);
725 device_release(self);
726 return error;
727 }
728
729 /* XXX: we should probably put these into dksubr.c, mostly */
730 static int
731 cgdwrite(dev_t dev, struct uio *uio, int flags)
732 {
733 device_t self;
734 int error;
735 struct cgd_softc *cs;
736 struct dk_softc *dksc;
737
738 DPRINTF_FOLLOW(("cgdwrite(0x%"PRIx64", %p, %d)\n", dev, uio, flags));
739 GETCGD_SOFTC(cs, dev, self);
740 dksc = &cs->sc_dksc;
741 if (!DK_ATTACHED(dksc)) {
742 device_release(self);
743 return ENXIO;
744 }
745 error = physio(cgdstrategy, NULL, dev, B_WRITE, minphys, uio);
746 device_release(self);
747 return error;
748 }
749
750 static int
751 cgdioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l)
752 {
753 device_t self;
754 struct cgd_softc *cs;
755 struct dk_softc *dksc;
756 int part = DISKPART(dev);
757 int pmask = 1 << part;
758 int error = 0;
759
760 DPRINTF_FOLLOW(("cgdioctl(0x%"PRIx64", %ld, %p, %d, %p)\n",
761 dev, cmd, data, flag, l));
762
763 switch (cmd) {
764 case CGDIOCGET:
765 return cgd_ioctl_get(dev, data, l);
766 case CGDIOCSET:
767 case CGDIOCCLR:
768 if ((flag & FWRITE) == 0)
769 return EBADF;
770 /* FALLTHROUGH */
771 default:
772 GETCGD_SOFTC(cs, dev, self);
773 dksc = &cs->sc_dksc;
774 break;
775 }
776
777 switch (cmd) {
778 case CGDIOCSET:
779 if (DK_ATTACHED(dksc))
780 error = EBUSY;
781 else
782 error = cgd_ioctl_set(cs, data, l);
783 break;
784 case CGDIOCCLR:
785 if (DK_BUSY(&cs->sc_dksc, pmask))
786 error = EBUSY;
787 else
788 error = cgd_ioctl_clr(cs, l);
789 break;
790 case DIOCGCACHE:
791 case DIOCCACHESYNC:
792 if (!DK_ATTACHED(dksc))
793 return ENOENT;
794 /*
795 * We pass this call down to the underlying disk.
796 */
797 else
798 error = VOP_IOCTL(cs->sc_tvn, cmd, data, flag,
799 l->l_cred);
800 break;
801 case DIOCGSTRATEGY:
802 case DIOCSSTRATEGY:
803 if (!DK_ATTACHED(dksc)) {
804 error = ENOENT;
805 break;
806 }
807 /*FALLTHROUGH*/
808 default:
809 error = dk_ioctl(dksc, dev, cmd, data, flag, l);
810 break;
811 case CGDIOCGET:
812 KASSERT(0);
813 error = EINVAL;
814 break;
815 }
816 device_release(self);
817 return error;
818 }
819
820 static int
821 cgddump(dev_t dev, daddr_t blkno, void *va, size_t size)
822 {
823 device_t self;
824 int error;
825 struct cgd_softc *cs;
826
827 DPRINTF_FOLLOW(("cgddump(0x%"PRIx64", %" PRId64 ", %p, %lu)\n",
828 dev, blkno, va, (unsigned long)size));
829 GETCGD_SOFTC(cs, dev, self);
830 error = dk_dump(&cs->sc_dksc, dev, blkno, va, size);
831 device_release(self);
832 return error;
833 }
834
835 /*
836 * XXXrcd:
837 * for now we hardcode the maximum key length.
838 */
839 #define MAX_KEYSIZE 1024
840
841 static const struct {
842 const char *n;
843 int v;
844 int d;
845 } encblkno[] = {
846 { "encblkno", CGD_CIPHER_CBC_ENCBLKNO8, 1 },
847 { "encblkno8", CGD_CIPHER_CBC_ENCBLKNO8, 1 },
848 { "encblkno1", CGD_CIPHER_CBC_ENCBLKNO1, 8 },
849 };
850
851 /* ARGSUSED */
852 static int
853 cgd_ioctl_set(struct cgd_softc *cs, void *data, struct lwp *l)
854 {
855 struct cgd_ioctl *ci = data;
856 struct vnode *vp;
857 int ret;
858 size_t i;
859 size_t keybytes; /* key length in bytes */
860 const char *cp;
861 struct pathbuf *pb;
862 char *inbuf;
863 struct dk_softc *dksc = &cs->sc_dksc;
864
865 cp = ci->ci_disk;
866
867 ret = pathbuf_copyin(ci->ci_disk, &pb);
868 if (ret != 0) {
869 return ret;
870 }
871 ret = dk_lookup(pb, l, &vp);
872 pathbuf_destroy(pb);
873 if (ret != 0) {
874 return ret;
875 }
876
877 inbuf = malloc(MAX_KEYSIZE, M_TEMP, M_WAITOK);
878
879 if ((ret = cgdinit(cs, cp, vp, l)) != 0)
880 goto bail;
881
882 (void)memset(inbuf, 0, MAX_KEYSIZE);
883 ret = copyinstr(ci->ci_alg, inbuf, 256, NULL);
884 if (ret)
885 goto bail;
886 cs->sc_cfuncs = cryptfuncs_find(inbuf);
887 if (!cs->sc_cfuncs) {
888 ret = EINVAL;
889 goto bail;
890 }
891
892 (void)memset(inbuf, 0, MAX_KEYSIZE);
893 ret = copyinstr(ci->ci_ivmethod, inbuf, MAX_KEYSIZE, NULL);
894 if (ret)
895 goto bail;
896
897 for (i = 0; i < __arraycount(encblkno); i++)
898 if (strcmp(encblkno[i].n, inbuf) == 0)
899 break;
900
901 if (i == __arraycount(encblkno)) {
902 ret = EINVAL;
903 goto bail;
904 }
905
906 keybytes = ci->ci_keylen / 8 + 1;
907 if (keybytes > MAX_KEYSIZE) {
908 ret = EINVAL;
909 goto bail;
910 }
911
912 (void)memset(inbuf, 0, MAX_KEYSIZE);
913 ret = copyin(ci->ci_key, inbuf, keybytes);
914 if (ret)
915 goto bail;
916
917 cs->sc_cdata.cf_blocksize = ci->ci_blocksize;
918 cs->sc_cdata.cf_mode = encblkno[i].v;
919 cs->sc_cdata.cf_keylen = ci->ci_keylen;
920 cs->sc_cdata.cf_priv = cs->sc_cfuncs->cf_init(ci->ci_keylen, inbuf,
921 &cs->sc_cdata.cf_blocksize);
922 if (cs->sc_cdata.cf_blocksize > CGD_MAXBLOCKSIZE) {
923 log(LOG_WARNING, "cgd: Disallowed cipher with blocksize %zu > %u\n",
924 cs->sc_cdata.cf_blocksize, CGD_MAXBLOCKSIZE);
925 cs->sc_cdata.cf_priv = NULL;
926 }
927
928 /*
929 * The blocksize is supposed to be in bytes. Unfortunately originally
930 * it was expressed in bits. For compatibility we maintain encblkno
931 * and encblkno8.
932 */
933 cs->sc_cdata.cf_blocksize /= encblkno[i].d;
934 (void)explicit_memset(inbuf, 0, MAX_KEYSIZE);
935 if (!cs->sc_cdata.cf_priv) {
936 ret = EINVAL; /* XXX is this the right error? */
937 goto bail;
938 }
939 free(inbuf, M_TEMP);
940
941 bufq_alloc(&dksc->sc_bufq, "fcfs", 0);
942
943 cs->sc_data = malloc(MAXPHYS, M_DEVBUF, M_WAITOK);
944 cs->sc_data_used = 0;
945
946 /* Attach the disk. */
947 dk_attach(dksc);
948 disk_attach(&dksc->sc_dkdev);
949
950 disk_set_info(dksc->sc_dev, &dksc->sc_dkdev, NULL);
951
952 /* Discover wedges on this disk. */
953 dkwedge_discover(&dksc->sc_dkdev);
954
955 return 0;
956
957 bail:
958 free(inbuf, M_TEMP);
959 (void)vn_close(vp, FREAD|FWRITE, l->l_cred);
960 return ret;
961 }
962
963 /* ARGSUSED */
964 static int
965 cgd_ioctl_clr(struct cgd_softc *cs, struct lwp *l)
966 {
967 struct dk_softc *dksc = &cs->sc_dksc;
968
969 if (!DK_ATTACHED(dksc))
970 return ENXIO;
971
972 /* Delete all of our wedges. */
973 dkwedge_delall(&dksc->sc_dkdev);
974
975 /* Kill off any queued buffers. */
976 dk_drain(dksc);
977 bufq_free(dksc->sc_bufq);
978
979 (void)vn_close(cs->sc_tvn, FREAD|FWRITE, l->l_cred);
980 cs->sc_cfuncs->cf_destroy(cs->sc_cdata.cf_priv);
981 free(cs->sc_tpath, M_DEVBUF);
982 free(cs->sc_data, M_DEVBUF);
983 cs->sc_data_used = 0;
984 dk_detach(dksc);
985 disk_detach(&dksc->sc_dkdev);
986
987 return 0;
988 }
989
990 static int
991 cgd_ioctl_get(dev_t dev, void *data, struct lwp *l)
992 {
993 device_t self;
994 struct cgd_softc *cs = getcgd_softc(dev, &self);
995 struct cgd_user *cgu;
996 int unit;
997 struct dk_softc *dksc = &cs->sc_dksc;
998
999 unit = CGDUNIT(dev);
1000 cgu = (struct cgd_user *)data;
1001
1002 DPRINTF_FOLLOW(("cgd_ioctl_get(0x%"PRIx64", %d, %p, %p)\n",
1003 dev, unit, data, l));
1004
1005 if (cgu->cgu_unit == -1)
1006 cgu->cgu_unit = unit;
1007
1008 if (cgu->cgu_unit < 0) {
1009 device_release(self);
1010 return EINVAL; /* XXX: should this be ENXIO? */
1011 }
1012
1013 /*
1014 * XXX This appears to be redundant, given the initialization
1015 * XXX when it was declared. Leave it for now, but don't
1016 * XXX take an extra reference to the device!
1017 */
1018 cs = device_lookup_private(&cgd_cd, unit);
1019 if (cs == NULL || !DK_ATTACHED(dksc)) {
1020 cgu->cgu_dev = 0;
1021 cgu->cgu_alg[0] = '\0';
1022 cgu->cgu_blocksize = 0;
1023 cgu->cgu_mode = 0;
1024 cgu->cgu_keylen = 0;
1025 }
1026 else {
1027 cgu->cgu_dev = cs->sc_tdev;
1028 strlcpy(cgu->cgu_alg, cs->sc_cfuncs->cf_name,
1029 sizeof(cgu->cgu_alg));
1030 cgu->cgu_blocksize = cs->sc_cdata.cf_blocksize;
1031 cgu->cgu_mode = cs->sc_cdata.cf_mode;
1032 cgu->cgu_keylen = cs->sc_cdata.cf_keylen;
1033 }
1034 device_release(self);
1035 return 0;
1036 }
1037
1038 static int
1039 cgdinit(struct cgd_softc *cs, const char *cpath, struct vnode *vp,
1040 struct lwp *l)
1041 {
1042 struct disk_geom *dg;
1043 int ret;
1044 char *tmppath;
1045 uint64_t psize;
1046 unsigned secsize;
1047 struct dk_softc *dksc = &cs->sc_dksc;
1048
1049 cs->sc_tvn = vp;
1050 cs->sc_tpath = NULL;
1051
1052 tmppath = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
1053 ret = copyinstr(cpath, tmppath, MAXPATHLEN, &cs->sc_tpathlen);
1054 if (ret)
1055 goto bail;
1056 cs->sc_tpath = malloc(cs->sc_tpathlen, M_DEVBUF, M_WAITOK);
1057 memcpy(cs->sc_tpath, tmppath, cs->sc_tpathlen);
1058
1059 cs->sc_tdev = vp->v_rdev;
1060
1061 if ((ret = getdisksize(vp, &psize, &secsize)) != 0)
1062 goto bail;
1063
1064 if (psize == 0) {
1065 ret = ENODEV;
1066 goto bail;
1067 }
1068
1069 /*
1070 * XXX here we should probe the underlying device. If we
1071 * are accessing a partition of type RAW_PART, then
1072 * we should populate our initial geometry with the
1073 * geometry that we discover from the device.
1074 */
1075 dg = &dksc->sc_dkdev.dk_geom;
1076 memset(dg, 0, sizeof(*dg));
1077 dg->dg_secperunit = psize;
1078 dg->dg_secsize = secsize;
1079 dg->dg_ntracks = 1;
1080 dg->dg_nsectors = 1024 * 1024 / dg->dg_secsize;
1081 dg->dg_ncylinders = dg->dg_secperunit / dg->dg_nsectors;
1082
1083 bail:
1084 free(tmppath, M_TEMP);
1085 if (ret && cs->sc_tpath)
1086 free(cs->sc_tpath, M_DEVBUF);
1087 return ret;
1088 }
1089
1090 /*
1091 * Our generic cipher entry point. This takes care of the
1092 * IV mode and passes off the work to the specific cipher.
1093 * We implement here the IV method ``encrypted block
1094 * number''.
1095 *
1096 * XXXrcd: for now we rely on our own crypto framework defined
1097 * in dev/cgd_crypto.c. This will change when we
1098 * get a generic kernel crypto framework.
1099 */
1100
1101 static void
1102 blkno2blkno_buf(char *sbuf, daddr_t blkno)
1103 {
1104 int i;
1105
1106 /* Set up the blkno in blkno_buf, here we do not care much
1107 * about the final layout of the information as long as we
1108 * can guarantee that each sector will have a different IV
1109 * and that the endianness of the machine will not affect
1110 * the representation that we have chosen.
1111 *
1112 * We choose this representation, because it does not rely
1113 * on the size of buf (which is the blocksize of the cipher),
1114 * but allows daddr_t to grow without breaking existing
1115 * disks.
1116 *
1117 * Note that blkno2blkno_buf does not take a size as input,
1118 * and hence must be called on a pre-zeroed buffer of length
1119 * greater than or equal to sizeof(daddr_t).
1120 */
1121 for (i=0; i < sizeof(daddr_t); i++) {
1122 *sbuf++ = blkno & 0xff;
1123 blkno >>= 8;
1124 }
1125 }
1126
1127 static void
1128 cgd_cipher(struct cgd_softc *cs, void *dstv, void *srcv,
1129 size_t len, daddr_t blkno, size_t secsize, int dir)
1130 {
1131 char *dst = dstv;
1132 char *src = srcv;
1133 cfunc_cipher_prep *ciprep = cs->sc_cfuncs->cf_cipher_prep;
1134 cfunc_cipher *cipher = cs->sc_cfuncs->cf_cipher;
1135 struct uio dstuio;
1136 struct uio srcuio;
1137 struct iovec dstiov[2];
1138 struct iovec srciov[2];
1139 size_t blocksize = cs->sc_cdata.cf_blocksize;
1140 size_t todo;
1141 char blkno_buf[CGD_MAXBLOCKSIZE], *iv;
1142
1143 DPRINTF_FOLLOW(("cgd_cipher() dir=%d\n", dir));
1144
1145 DIAGCONDPANIC(len % blocksize != 0,
1146 ("cgd_cipher: len %% blocksize != 0"));
1147
1148 /* ensure that sizeof(daddr_t) <= blocksize (for encblkno IVing) */
1149 DIAGCONDPANIC(sizeof(daddr_t) > blocksize,
1150 ("cgd_cipher: sizeof(daddr_t) > blocksize"));
1151
1152 DIAGCONDPANIC(blocksize > CGD_MAXBLOCKSIZE,
1153 ("cgd_cipher: blocksize > CGD_MAXBLOCKSIZE"));
1154
1155 dstuio.uio_iov = dstiov;
1156 dstuio.uio_iovcnt = 1;
1157
1158 srcuio.uio_iov = srciov;
1159 srcuio.uio_iovcnt = 1;
1160
1161 for (; len > 0; len -= todo) {
1162 todo = MIN(len, secsize);
1163
1164 dstiov[0].iov_base = dst;
1165 srciov[0].iov_base = src;
1166 dstiov[0].iov_len = todo;
1167 srciov[0].iov_len = todo;
1168
1169 memset(blkno_buf, 0x0, blocksize);
1170 blkno2blkno_buf(blkno_buf, blkno);
1171 IFDEBUG(CGDB_CRYPTO, hexprint("step 1: blkno_buf",
1172 blkno_buf, blocksize));
1173
1174 /*
1175 * Compute an initial IV. All ciphers
1176 * can convert blkno_buf in-place.
1177 */
1178 iv = blkno_buf;
1179 ciprep(cs->sc_cdata.cf_priv, iv, blkno_buf, blocksize, dir);
1180 IFDEBUG(CGDB_CRYPTO, hexprint("step 2: iv", iv, blocksize));
1181
1182 cipher(cs->sc_cdata.cf_priv, &dstuio, &srcuio, iv, dir);
1183
1184 dst += todo;
1185 src += todo;
1186 blkno++;
1187 }
1188 }
1189
1190 #ifdef DEBUG
1191 static void
1192 hexprint(const char *start, void *buf, int len)
1193 {
1194 char *c = buf;
1195
1196 DIAGCONDPANIC(len < 0, ("hexprint: called with len < 0"));
1197 printf("%s: len=%06d 0x", start, len);
1198 while (len--)
1199 printf("%02x", (unsigned char) *c++);
1200 }
1201 #endif
1202
1203 static void
1204 selftest(void)
1205 {
1206 struct cgd_softc cs;
1207 void *buf;
1208
1209 printf("running cgd selftest ");
1210
1211 for (size_t i = 0; i < __arraycount(selftests); i++) {
1212 const char *alg = selftests[i].alg;
1213 const uint8_t *key = selftests[i].key;
1214 int keylen = selftests[i].keylen;
1215 int txtlen = selftests[i].txtlen;
1216
1217 printf("%s-%d ", alg, keylen);
1218
1219 memset(&cs, 0, sizeof(cs));
1220
1221 cs.sc_cfuncs = cryptfuncs_find(alg);
1222 if (cs.sc_cfuncs == NULL)
1223 panic("%s not implemented", alg);
1224
1225 cs.sc_cdata.cf_blocksize = 8 * selftests[i].blocksize;
1226 cs.sc_cdata.cf_mode = CGD_CIPHER_CBC_ENCBLKNO1;
1227 cs.sc_cdata.cf_keylen = keylen;
1228
1229 cs.sc_cdata.cf_priv = cs.sc_cfuncs->cf_init(keylen,
1230 key, &cs.sc_cdata.cf_blocksize);
1231 if (cs.sc_cdata.cf_priv == NULL)
1232 panic("cf_priv is NULL");
1233 if (cs.sc_cdata.cf_blocksize > CGD_MAXBLOCKSIZE)
1234 panic("bad block size %zu", cs.sc_cdata.cf_blocksize);
1235
1236 cs.sc_cdata.cf_blocksize /= 8;
1237
1238 buf = malloc(txtlen, M_DEVBUF, M_WAITOK);
1239 memcpy(buf, selftests[i].ptxt, txtlen);
1240
1241 cgd_cipher(&cs, buf, buf, txtlen, selftests[i].blkno,
1242 selftests[i].secsize, CGD_CIPHER_ENCRYPT);
1243 if (memcmp(buf, selftests[i].ctxt, txtlen) != 0)
1244 panic("encryption is broken");
1245
1246 cgd_cipher(&cs, buf, buf, txtlen, selftests[i].blkno,
1247 selftests[i].secsize, CGD_CIPHER_DECRYPT);
1248 if (memcmp(buf, selftests[i].ptxt, txtlen) != 0)
1249 panic("decryption is broken");
1250
1251 free(buf, M_DEVBUF);
1252 cs.sc_cfuncs->cf_destroy(cs.sc_cdata.cf_priv);
1253 }
1254
1255 printf("done\n");
1256 }
1257
1258 MODULE(MODULE_CLASS_DRIVER, cgd, "blowfish,des,dk_subr");
1259
1260 #ifdef _MODULE
1261 CFDRIVER_DECL(cgd, DV_DISK, NULL);
1262
1263 devmajor_t cgd_bmajor = -1, cgd_cmajor = -1;
1264 #endif
1265
1266 static int
1267 cgd_modcmd(modcmd_t cmd, void *arg)
1268 {
1269 int error = 0;
1270
1271 switch (cmd) {
1272 case MODULE_CMD_INIT:
1273 selftest();
1274 #ifdef _MODULE
1275 error = config_cfdriver_attach(&cgd_cd);
1276 if (error)
1277 break;
1278
1279 error = config_cfattach_attach(cgd_cd.cd_name, &cgd_ca);
1280 if (error) {
1281 config_cfdriver_detach(&cgd_cd);
1282 aprint_error("%s: unable to register cfattach for "
1283 "%s, error %d\n", __func__, cgd_cd.cd_name, error);
1284 break;
1285 }
1286 /*
1287 * Attach the {b,c}devsw's
1288 */
1289 error = devsw_attach("cgd", &cgd_bdevsw, &cgd_bmajor,
1290 &cgd_cdevsw, &cgd_cmajor);
1291
1292 /*
1293 * If devsw_attach fails, remove from autoconf database
1294 */
1295 if (error) {
1296 config_cfattach_detach(cgd_cd.cd_name, &cgd_ca);
1297 config_cfdriver_detach(&cgd_cd);
1298 aprint_error("%s: unable to attach %s devsw, "
1299 "error %d", __func__, cgd_cd.cd_name, error);
1300 break;
1301 }
1302 #endif
1303 break;
1304
1305 case MODULE_CMD_FINI:
1306 #ifdef _MODULE
1307 /*
1308 * Remove {b,c}devsw's
1309 */
1310 devsw_detach(&cgd_bdevsw, &cgd_cdevsw);
1311
1312 /*
1313 * Now remove device from autoconf database
1314 */
1315 error = config_cfattach_detach(cgd_cd.cd_name, &cgd_ca);
1316 if (error) {
1317 (void)devsw_attach("cgd", &cgd_bdevsw, &cgd_bmajor,
1318 &cgd_cdevsw, &cgd_cmajor);
1319 aprint_error("%s: failed to detach %s cfattach, "
1320 "error %d\n", __func__, cgd_cd.cd_name, error);
1321 break;
1322 }
1323 error = config_cfdriver_detach(&cgd_cd);
1324 if (error) {
1325 (void)config_cfattach_attach(cgd_cd.cd_name, &cgd_ca);
1326 (void)devsw_attach("cgd", &cgd_bdevsw, &cgd_bmajor,
1327 &cgd_cdevsw, &cgd_cmajor);
1328 aprint_error("%s: failed to detach %s cfdriver, "
1329 "error %d\n", __func__, cgd_cd.cd_name, error);
1330 break;
1331 }
1332 #endif
1333 break;
1334
1335 case MODULE_CMD_STAT:
1336 error = ENOTTY;
1337 break;
1338 default:
1339 error = ENOTTY;
1340 break;
1341 }
1342
1343 return error;
1344 }
1345