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