cgd.c revision 1.114.4.6 1 /* $NetBSD: cgd.c,v 1.114.4.6 2017/04/29 10:50:46 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.6 2017/04/29 10:50:46 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 (config_attach_pseudo(cf) == NULL)
386 return NULL;
387
388 if ((*self = device_lookup_acquire(&cgd_cd, unit)) == NULL)
389 return NULL;
390 else {
391 /*
392 * Note that we return while still holding a reference
393 * to the device!
394 */
395 sc = device_private(*self);
396 return sc;
397 }
398 }
399
400 static int
401 cgd_destroy(device_t dev)
402 {
403 int error;
404 cfdata_t cf;
405
406 cf = device_cfdata(dev);
407 error = config_detach_release(dev, DETACH_QUIET);
408 if (error == 0)
409 free(cf, M_DEVBUF);
410
411 return error;
412 }
413
414 static int
415 cgdopen(dev_t dev, int flags, int fmt, struct lwp *l)
416 {
417 device_t self;
418 int error;
419 struct cgd_softc *cs;
420
421 DPRINTF_FOLLOW(("cgdopen(0x%"PRIx64", %d)\n", dev, flags));
422 GETCGD_SOFTC(cs, dev, self);
423 error = dk_open(&cs->sc_dksc, dev, flags, fmt, l);
424 device_release(self);
425 return error;
426 }
427
428 static int
429 cgdclose(dev_t dev, int flags, int fmt, struct lwp *l)
430 {
431 int error;
432 device_t self;
433 struct cgd_softc *cs;
434 struct dk_softc *dksc;
435
436 DPRINTF_FOLLOW(("cgdclose(0x%"PRIx64", %d)\n", dev, flags));
437 GETCGD_SOFTC(cs, dev, self);
438 dksc = &cs->sc_dksc;
439 if ((error = dk_close(dksc, dev, flags, fmt, l)) != 0) {
440 device_release(self);
441 return error;
442 }
443
444 if (!DK_ATTACHED(dksc)) {
445 if ((error = cgd_destroy(cs->sc_dksc.sc_dev)) != 0) {
446 aprint_error_dev(dksc->sc_dev,
447 "unable to detach instance\n");
448 }
449 return error;
450 }
451
452 /* Unit is still attached - just return */
453 device_release(self);
454 return 0;
455 }
456
457 static void
458 cgdstrategy(struct buf *bp)
459 {
460 device_t self;
461 struct cgd_softc *cs = getcgd_softc(bp->b_dev, &self);
462
463 DPRINTF_FOLLOW(("cgdstrategy(%p): b_bcount = %ld\n", bp,
464 (long)bp->b_bcount));
465
466 if (!cs) {
467 bp->b_error = ENXIO;
468 goto bail;
469 }
470
471 /*
472 * Reject unaligned writes.
473 */
474 if (((uintptr_t)bp->b_data & 3) != 0) {
475 bp->b_error = EINVAL;
476 goto bail;
477 }
478
479 dk_strategy(&cs->sc_dksc, bp);
480 device_release(self);
481 return;
482
483 bail:
484 bp->b_resid = bp->b_bcount;
485 biodone(bp);
486 if (self)
487 device_release(self);
488 return;
489 }
490
491 static int
492 cgdsize(dev_t dev)
493 {
494 int retval;
495 device_t self;
496 struct cgd_softc *cs = getcgd_softc(dev, &self);
497
498 DPRINTF_FOLLOW(("cgdsize(0x%"PRIx64")\n", dev));
499 if (!cs)
500 retval = -1;
501 else
502 retval = dk_size(&cs->sc_dksc, dev);
503
504 device_release(self);
505 return retval;
506 }
507
508 /*
509 * cgd_{get,put}data are functions that deal with getting a buffer
510 * for the new encrypted data. We have a buffer per device so that
511 * we can ensure that we can always have a transaction in flight.
512 * We use this buffer first so that we have one less piece of
513 * malloc'ed data at any given point.
514 */
515
516 static void *
517 cgd_getdata(struct dk_softc *dksc, unsigned long size)
518 {
519 struct cgd_softc *cs = (struct cgd_softc *)dksc;
520 void * data = NULL;
521
522 mutex_enter(&cs->sc_lock);
523 if (cs->sc_data_used == 0) {
524 cs->sc_data_used = 1;
525 data = cs->sc_data;
526 }
527 mutex_exit(&cs->sc_lock);
528
529 if (data)
530 return data;
531
532 return malloc(size, M_DEVBUF, M_NOWAIT);
533 }
534
535 static void
536 cgd_putdata(struct dk_softc *dksc, void *data)
537 {
538 struct cgd_softc *cs = (struct cgd_softc *)dksc;
539
540 if (data == cs->sc_data) {
541 mutex_enter(&cs->sc_lock);
542 cs->sc_data_used = 0;
543 mutex_exit(&cs->sc_lock);
544 } else {
545 free(data, M_DEVBUF);
546 }
547 }
548
549 static int
550 cgd_diskstart(device_t dev, struct buf *bp)
551 {
552 struct cgd_softc *cs = device_private(dev);
553 struct dk_softc *dksc = &cs->sc_dksc;
554 struct disk_geom *dg = &dksc->sc_dkdev.dk_geom;
555 struct buf *nbp;
556 void * addr;
557 void * newaddr;
558 daddr_t bn;
559 struct vnode *vp;
560
561 DPRINTF_FOLLOW(("cgd_diskstart(%p, %p)\n", dksc, bp));
562
563 bn = bp->b_rawblkno;
564
565 /*
566 * We attempt to allocate all of our resources up front, so that
567 * we can fail quickly if they are unavailable.
568 */
569 nbp = getiobuf(cs->sc_tvn, false);
570 if (nbp == NULL)
571 return EAGAIN;
572
573 /*
574 * If we are writing, then we need to encrypt the outgoing
575 * block into a new block of memory.
576 */
577 newaddr = addr = bp->b_data;
578 if ((bp->b_flags & B_READ) == 0) {
579 newaddr = cgd_getdata(dksc, bp->b_bcount);
580 if (!newaddr) {
581 putiobuf(nbp);
582 return EAGAIN;
583 }
584 cgd_cipher(cs, newaddr, addr, bp->b_bcount, bn,
585 dg->dg_secsize, CGD_CIPHER_ENCRYPT);
586 }
587
588 nbp->b_data = newaddr;
589 nbp->b_flags = bp->b_flags;
590 nbp->b_oflags = bp->b_oflags;
591 nbp->b_cflags = bp->b_cflags;
592 nbp->b_iodone = cgdiodone;
593 nbp->b_proc = bp->b_proc;
594 nbp->b_blkno = btodb(bn * dg->dg_secsize);
595 nbp->b_bcount = bp->b_bcount;
596 nbp->b_private = bp;
597
598 BIO_COPYPRIO(nbp, bp);
599
600 if ((nbp->b_flags & B_READ) == 0) {
601 vp = nbp->b_vp;
602 mutex_enter(vp->v_interlock);
603 vp->v_numoutput++;
604 mutex_exit(vp->v_interlock);
605 }
606 VOP_STRATEGY(cs->sc_tvn, nbp);
607
608 return 0;
609 }
610
611 static void
612 cgdiodone(struct buf *nbp)
613 {
614 device_t self;
615 struct buf *obp = nbp->b_private;
616 struct cgd_softc *cs = getcgd_softc(obp->b_dev, &self);
617 struct dk_softc *dksc = &cs->sc_dksc;
618 struct disk_geom *dg = &dksc->sc_dkdev.dk_geom;
619 daddr_t bn;
620
621 KDASSERT(cs);
622
623 DPRINTF_FOLLOW(("cgdiodone(%p)\n", nbp));
624 DPRINTF(CGDB_IO, ("cgdiodone: bp %p bcount %d resid %d\n",
625 obp, obp->b_bcount, obp->b_resid));
626 DPRINTF(CGDB_IO, (" dev 0x%"PRIx64", nbp %p bn %" PRId64
627 " addr %p bcnt %d\n", nbp->b_dev, nbp, nbp->b_blkno, nbp->b_data,
628 nbp->b_bcount));
629 if (nbp->b_error != 0) {
630 obp->b_error = nbp->b_error;
631 DPRINTF(CGDB_IO, ("%s: error %d\n", dksc->sc_xname,
632 obp->b_error));
633 }
634
635 /* Perform the decryption if we are reading.
636 *
637 * Note: use the blocknumber from nbp, since it is what
638 * we used to encrypt the blocks.
639 */
640
641 if (nbp->b_flags & B_READ) {
642 bn = dbtob(nbp->b_blkno) / dg->dg_secsize;
643 cgd_cipher(cs, obp->b_data, obp->b_data, obp->b_bcount,
644 bn, dg->dg_secsize, CGD_CIPHER_DECRYPT);
645 }
646
647 /* If we allocated memory, free it now... */
648 if (nbp->b_data != obp->b_data)
649 cgd_putdata(dksc, nbp->b_data);
650
651 putiobuf(nbp);
652
653 /* Request is complete for whatever reason */
654 obp->b_resid = 0;
655 if (obp->b_error != 0)
656 obp->b_resid = obp->b_bcount;
657
658 dk_done(dksc, obp);
659 device_release(self);
660
661 dk_start(dksc, NULL);
662 }
663
664 static int
665 cgd_dumpblocks(device_t dev, void *va, daddr_t blkno, int nblk)
666 {
667 struct cgd_softc *sc = device_private(dev);
668 struct dk_softc *dksc = &sc->sc_dksc;
669 struct disk_geom *dg = &dksc->sc_dkdev.dk_geom;
670 size_t nbytes, blksize;
671 void *buf;
672 int error;
673
674 /*
675 * dk_dump gives us units of disklabel sectors. Everything
676 * else in cgd uses units of diskgeom sectors. These had
677 * better agree; otherwise we need to figure out how to convert
678 * between them.
679 */
680 KASSERTMSG((dg->dg_secsize == dksc->sc_dkdev.dk_label->d_secsize),
681 "diskgeom secsize %"PRIu32" != disklabel secsize %"PRIu32,
682 dg->dg_secsize, dksc->sc_dkdev.dk_label->d_secsize);
683 blksize = dg->dg_secsize;
684
685 /*
686 * Compute the number of bytes in this request, which dk_dump
687 * has `helpfully' converted to a number of blocks for us.
688 */
689 nbytes = nblk*blksize;
690
691 /* Try to acquire a buffer to store the ciphertext. */
692 buf = cgd_getdata(dksc, nbytes);
693 if (buf == NULL)
694 /* Out of memory: give up. */
695 return ENOMEM;
696
697 /* Encrypt the caller's data into the temporary buffer. */
698 cgd_cipher(sc, buf, va, nbytes, blkno, blksize, CGD_CIPHER_ENCRYPT);
699
700 /* Pass it on to the underlying disk device. */
701 error = bdev_dump(sc->sc_tdev, blkno, buf, nbytes);
702
703 /* Release the buffer. */
704 cgd_putdata(dksc, buf);
705
706 /* Return any error from the underlying disk device. */
707 return error;
708 }
709
710 /* XXX: we should probably put these into dksubr.c, mostly */
711 static int
712 cgdread(dev_t dev, struct uio *uio, int flags)
713 {
714 device_t self;
715 int error;
716 struct cgd_softc *cs;
717 struct dk_softc *dksc;
718
719 DPRINTF_FOLLOW(("cgdread(0x%llx, %p, %d)\n",
720 (unsigned long long)dev, uio, flags));
721 GETCGD_SOFTC(cs, dev, self);
722 dksc = &cs->sc_dksc;
723 if (!DK_ATTACHED(dksc)) {
724 device_release(self);
725 return ENXIO;
726 }
727 error = physio(cgdstrategy, NULL, dev, B_READ, minphys, uio);
728 device_release(self);
729 return error;
730 }
731
732 /* XXX: we should probably put these into dksubr.c, mostly */
733 static int
734 cgdwrite(dev_t dev, struct uio *uio, int flags)
735 {
736 device_t self;
737 int error;
738 struct cgd_softc *cs;
739 struct dk_softc *dksc;
740
741 DPRINTF_FOLLOW(("cgdwrite(0x%"PRIx64", %p, %d)\n", dev, uio, flags));
742 GETCGD_SOFTC(cs, dev, self);
743 dksc = &cs->sc_dksc;
744 if (!DK_ATTACHED(dksc)) {
745 device_release(self);
746 return ENXIO;
747 }
748 error = physio(cgdstrategy, NULL, dev, B_WRITE, minphys, uio);
749 device_release(self);
750 return error;
751 }
752
753 static int
754 cgdioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l)
755 {
756 device_t self;
757 struct cgd_softc *cs;
758 struct dk_softc *dksc;
759 int part = DISKPART(dev);
760 int pmask = 1 << part;
761 int error = 0;
762
763 DPRINTF_FOLLOW(("cgdioctl(0x%"PRIx64", %ld, %p, %d, %p)\n",
764 dev, cmd, data, flag, l));
765
766 switch (cmd) {
767 case CGDIOCGET:
768 return cgd_ioctl_get(dev, data, l);
769 case CGDIOCSET:
770 case CGDIOCCLR:
771 if ((flag & FWRITE) == 0)
772 return EBADF;
773 /* FALLTHROUGH */
774 default:
775 GETCGD_SOFTC(cs, dev, self);
776 dksc = &cs->sc_dksc;
777 break;
778 }
779
780 switch (cmd) {
781 case CGDIOCSET:
782 if (DK_ATTACHED(dksc))
783 error = EBUSY;
784 else
785 error = cgd_ioctl_set(cs, data, l);
786 break;
787 case CGDIOCCLR:
788 if (DK_BUSY(&cs->sc_dksc, pmask))
789 error = EBUSY;
790 else
791 error = cgd_ioctl_clr(cs, l);
792 break;
793 case DIOCGCACHE:
794 case DIOCCACHESYNC:
795 if (!DK_ATTACHED(dksc))
796 return ENOENT;
797 /*
798 * We pass this call down to the underlying disk.
799 */
800 else
801 error = VOP_IOCTL(cs->sc_tvn, cmd, data, flag,
802 l->l_cred);
803 break;
804 case DIOCGSTRATEGY:
805 case DIOCSSTRATEGY:
806 if (!DK_ATTACHED(dksc)) {
807 error = ENOENT;
808 break;
809 }
810 /*FALLTHROUGH*/
811 default:
812 error = dk_ioctl(dksc, dev, cmd, data, flag, l);
813 break;
814 case CGDIOCGET:
815 KASSERT(0);
816 error = EINVAL;
817 break;
818 }
819 device_release(self);
820 return error;
821 }
822
823 static int
824 cgddump(dev_t dev, daddr_t blkno, void *va, size_t size)
825 {
826 device_t self;
827 int error;
828 struct cgd_softc *cs;
829
830 DPRINTF_FOLLOW(("cgddump(0x%"PRIx64", %" PRId64 ", %p, %lu)\n",
831 dev, blkno, va, (unsigned long)size));
832 GETCGD_SOFTC(cs, dev, self);
833 error = dk_dump(&cs->sc_dksc, dev, blkno, va, size);
834 device_release(self);
835 return error;
836 }
837
838 /*
839 * XXXrcd:
840 * for now we hardcode the maximum key length.
841 */
842 #define MAX_KEYSIZE 1024
843
844 static const struct {
845 const char *n;
846 int v;
847 int d;
848 } encblkno[] = {
849 { "encblkno", CGD_CIPHER_CBC_ENCBLKNO8, 1 },
850 { "encblkno8", CGD_CIPHER_CBC_ENCBLKNO8, 1 },
851 { "encblkno1", CGD_CIPHER_CBC_ENCBLKNO1, 8 },
852 };
853
854 /* ARGSUSED */
855 static int
856 cgd_ioctl_set(struct cgd_softc *cs, void *data, struct lwp *l)
857 {
858 struct cgd_ioctl *ci = data;
859 struct vnode *vp;
860 int ret;
861 size_t i;
862 size_t keybytes; /* key length in bytes */
863 const char *cp;
864 struct pathbuf *pb;
865 char *inbuf;
866 struct dk_softc *dksc = &cs->sc_dksc;
867
868 cp = ci->ci_disk;
869
870 ret = pathbuf_copyin(ci->ci_disk, &pb);
871 if (ret != 0) {
872 return ret;
873 }
874 ret = dk_lookup(pb, l, &vp);
875 pathbuf_destroy(pb);
876 if (ret != 0) {
877 return ret;
878 }
879
880 inbuf = malloc(MAX_KEYSIZE, M_TEMP, M_WAITOK);
881
882 if ((ret = cgdinit(cs, cp, vp, l)) != 0)
883 goto bail;
884
885 (void)memset(inbuf, 0, MAX_KEYSIZE);
886 ret = copyinstr(ci->ci_alg, inbuf, 256, NULL);
887 if (ret)
888 goto bail;
889 cs->sc_cfuncs = cryptfuncs_find(inbuf);
890 if (!cs->sc_cfuncs) {
891 ret = EINVAL;
892 goto bail;
893 }
894
895 (void)memset(inbuf, 0, MAX_KEYSIZE);
896 ret = copyinstr(ci->ci_ivmethod, inbuf, MAX_KEYSIZE, NULL);
897 if (ret)
898 goto bail;
899
900 for (i = 0; i < __arraycount(encblkno); i++)
901 if (strcmp(encblkno[i].n, inbuf) == 0)
902 break;
903
904 if (i == __arraycount(encblkno)) {
905 ret = EINVAL;
906 goto bail;
907 }
908
909 keybytes = ci->ci_keylen / 8 + 1;
910 if (keybytes > MAX_KEYSIZE) {
911 ret = EINVAL;
912 goto bail;
913 }
914
915 (void)memset(inbuf, 0, MAX_KEYSIZE);
916 ret = copyin(ci->ci_key, inbuf, keybytes);
917 if (ret)
918 goto bail;
919
920 cs->sc_cdata.cf_blocksize = ci->ci_blocksize;
921 cs->sc_cdata.cf_mode = encblkno[i].v;
922 cs->sc_cdata.cf_keylen = ci->ci_keylen;
923 cs->sc_cdata.cf_priv = cs->sc_cfuncs->cf_init(ci->ci_keylen, inbuf,
924 &cs->sc_cdata.cf_blocksize);
925 if (cs->sc_cdata.cf_blocksize > CGD_MAXBLOCKSIZE) {
926 log(LOG_WARNING, "cgd: Disallowed cipher with blocksize %zu > %u\n",
927 cs->sc_cdata.cf_blocksize, CGD_MAXBLOCKSIZE);
928 cs->sc_cdata.cf_priv = NULL;
929 }
930
931 /*
932 * The blocksize is supposed to be in bytes. Unfortunately originally
933 * it was expressed in bits. For compatibility we maintain encblkno
934 * and encblkno8.
935 */
936 cs->sc_cdata.cf_blocksize /= encblkno[i].d;
937 (void)explicit_memset(inbuf, 0, MAX_KEYSIZE);
938 if (!cs->sc_cdata.cf_priv) {
939 ret = EINVAL; /* XXX is this the right error? */
940 goto bail;
941 }
942 free(inbuf, M_TEMP);
943
944 bufq_alloc(&dksc->sc_bufq, "fcfs", 0);
945
946 cs->sc_data = malloc(MAXPHYS, M_DEVBUF, M_WAITOK);
947 cs->sc_data_used = 0;
948
949 /* Attach the disk. */
950 dk_attach(dksc);
951 disk_attach(&dksc->sc_dkdev);
952
953 disk_set_info(dksc->sc_dev, &dksc->sc_dkdev, NULL);
954
955 /* Discover wedges on this disk. */
956 dkwedge_discover(&dksc->sc_dkdev);
957
958 return 0;
959
960 bail:
961 free(inbuf, M_TEMP);
962 (void)vn_close(vp, FREAD|FWRITE, l->l_cred);
963 return ret;
964 }
965
966 /* ARGSUSED */
967 static int
968 cgd_ioctl_clr(struct cgd_softc *cs, struct lwp *l)
969 {
970 struct dk_softc *dksc = &cs->sc_dksc;
971
972 if (!DK_ATTACHED(dksc))
973 return ENXIO;
974
975 /* Delete all of our wedges. */
976 dkwedge_delall(&dksc->sc_dkdev);
977
978 /* Kill off any queued buffers. */
979 dk_drain(dksc);
980 bufq_free(dksc->sc_bufq);
981
982 (void)vn_close(cs->sc_tvn, FREAD|FWRITE, l->l_cred);
983 cs->sc_cfuncs->cf_destroy(cs->sc_cdata.cf_priv);
984 free(cs->sc_tpath, M_DEVBUF);
985 free(cs->sc_data, M_DEVBUF);
986 cs->sc_data_used = 0;
987 dk_detach(dksc);
988 disk_detach(&dksc->sc_dkdev);
989
990 return 0;
991 }
992
993 static int
994 cgd_ioctl_get(dev_t dev, void *data, struct lwp *l)
995 {
996 device_t self;
997 struct cgd_softc *cs = getcgd_softc(dev, &self);
998 struct cgd_user *cgu;
999 int unit;
1000 struct dk_softc *dksc = &cs->sc_dksc;
1001
1002 unit = CGDUNIT(dev);
1003 cgu = (struct cgd_user *)data;
1004
1005 DPRINTF_FOLLOW(("cgd_ioctl_get(0x%"PRIx64", %d, %p, %p)\n",
1006 dev, unit, data, l));
1007
1008 if (cgu->cgu_unit == -1)
1009 cgu->cgu_unit = unit;
1010
1011 if (cgu->cgu_unit < 0) {
1012 device_release(self);
1013 return EINVAL; /* XXX: should this be ENXIO? */
1014 }
1015
1016 /*
1017 * XXX This appears to be redundant, given the initialization
1018 * XXX when it was declared. Leave it for now, but don't
1019 * XXX take an extra reference to the device!
1020 */
1021 cs = device_lookup_private(&cgd_cd, unit);
1022 if (cs == NULL || !DK_ATTACHED(dksc)) {
1023 cgu->cgu_dev = 0;
1024 cgu->cgu_alg[0] = '\0';
1025 cgu->cgu_blocksize = 0;
1026 cgu->cgu_mode = 0;
1027 cgu->cgu_keylen = 0;
1028 }
1029 else {
1030 cgu->cgu_dev = cs->sc_tdev;
1031 strlcpy(cgu->cgu_alg, cs->sc_cfuncs->cf_name,
1032 sizeof(cgu->cgu_alg));
1033 cgu->cgu_blocksize = cs->sc_cdata.cf_blocksize;
1034 cgu->cgu_mode = cs->sc_cdata.cf_mode;
1035 cgu->cgu_keylen = cs->sc_cdata.cf_keylen;
1036 }
1037 device_release(self);
1038 return 0;
1039 }
1040
1041 static int
1042 cgdinit(struct cgd_softc *cs, const char *cpath, struct vnode *vp,
1043 struct lwp *l)
1044 {
1045 struct disk_geom *dg;
1046 int ret;
1047 char *tmppath;
1048 uint64_t psize;
1049 unsigned secsize;
1050 struct dk_softc *dksc = &cs->sc_dksc;
1051
1052 cs->sc_tvn = vp;
1053 cs->sc_tpath = NULL;
1054
1055 tmppath = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
1056 ret = copyinstr(cpath, tmppath, MAXPATHLEN, &cs->sc_tpathlen);
1057 if (ret)
1058 goto bail;
1059 cs->sc_tpath = malloc(cs->sc_tpathlen, M_DEVBUF, M_WAITOK);
1060 memcpy(cs->sc_tpath, tmppath, cs->sc_tpathlen);
1061
1062 cs->sc_tdev = vp->v_rdev;
1063
1064 if ((ret = getdisksize(vp, &psize, &secsize)) != 0)
1065 goto bail;
1066
1067 if (psize == 0) {
1068 ret = ENODEV;
1069 goto bail;
1070 }
1071
1072 /*
1073 * XXX here we should probe the underlying device. If we
1074 * are accessing a partition of type RAW_PART, then
1075 * we should populate our initial geometry with the
1076 * geometry that we discover from the device.
1077 */
1078 dg = &dksc->sc_dkdev.dk_geom;
1079 memset(dg, 0, sizeof(*dg));
1080 dg->dg_secperunit = psize;
1081 dg->dg_secsize = secsize;
1082 dg->dg_ntracks = 1;
1083 dg->dg_nsectors = 1024 * 1024 / dg->dg_secsize;
1084 dg->dg_ncylinders = dg->dg_secperunit / dg->dg_nsectors;
1085
1086 bail:
1087 free(tmppath, M_TEMP);
1088 if (ret && cs->sc_tpath)
1089 free(cs->sc_tpath, M_DEVBUF);
1090 return ret;
1091 }
1092
1093 /*
1094 * Our generic cipher entry point. This takes care of the
1095 * IV mode and passes off the work to the specific cipher.
1096 * We implement here the IV method ``encrypted block
1097 * number''.
1098 *
1099 * XXXrcd: for now we rely on our own crypto framework defined
1100 * in dev/cgd_crypto.c. This will change when we
1101 * get a generic kernel crypto framework.
1102 */
1103
1104 static void
1105 blkno2blkno_buf(char *sbuf, daddr_t blkno)
1106 {
1107 int i;
1108
1109 /* Set up the blkno in blkno_buf, here we do not care much
1110 * about the final layout of the information as long as we
1111 * can guarantee that each sector will have a different IV
1112 * and that the endianness of the machine will not affect
1113 * the representation that we have chosen.
1114 *
1115 * We choose this representation, because it does not rely
1116 * on the size of buf (which is the blocksize of the cipher),
1117 * but allows daddr_t to grow without breaking existing
1118 * disks.
1119 *
1120 * Note that blkno2blkno_buf does not take a size as input,
1121 * and hence must be called on a pre-zeroed buffer of length
1122 * greater than or equal to sizeof(daddr_t).
1123 */
1124 for (i=0; i < sizeof(daddr_t); i++) {
1125 *sbuf++ = blkno & 0xff;
1126 blkno >>= 8;
1127 }
1128 }
1129
1130 static void
1131 cgd_cipher(struct cgd_softc *cs, void *dstv, void *srcv,
1132 size_t len, daddr_t blkno, size_t secsize, int dir)
1133 {
1134 char *dst = dstv;
1135 char *src = srcv;
1136 cfunc_cipher_prep *ciprep = cs->sc_cfuncs->cf_cipher_prep;
1137 cfunc_cipher *cipher = cs->sc_cfuncs->cf_cipher;
1138 struct uio dstuio;
1139 struct uio srcuio;
1140 struct iovec dstiov[2];
1141 struct iovec srciov[2];
1142 size_t blocksize = cs->sc_cdata.cf_blocksize;
1143 size_t todo;
1144 char blkno_buf[CGD_MAXBLOCKSIZE], *iv;
1145
1146 DPRINTF_FOLLOW(("cgd_cipher() dir=%d\n", dir));
1147
1148 DIAGCONDPANIC(len % blocksize != 0,
1149 ("cgd_cipher: len %% blocksize != 0"));
1150
1151 /* ensure that sizeof(daddr_t) <= blocksize (for encblkno IVing) */
1152 DIAGCONDPANIC(sizeof(daddr_t) > blocksize,
1153 ("cgd_cipher: sizeof(daddr_t) > blocksize"));
1154
1155 DIAGCONDPANIC(blocksize > CGD_MAXBLOCKSIZE,
1156 ("cgd_cipher: blocksize > CGD_MAXBLOCKSIZE"));
1157
1158 dstuio.uio_iov = dstiov;
1159 dstuio.uio_iovcnt = 1;
1160
1161 srcuio.uio_iov = srciov;
1162 srcuio.uio_iovcnt = 1;
1163
1164 for (; len > 0; len -= todo) {
1165 todo = MIN(len, secsize);
1166
1167 dstiov[0].iov_base = dst;
1168 srciov[0].iov_base = src;
1169 dstiov[0].iov_len = todo;
1170 srciov[0].iov_len = todo;
1171
1172 memset(blkno_buf, 0x0, blocksize);
1173 blkno2blkno_buf(blkno_buf, blkno);
1174 IFDEBUG(CGDB_CRYPTO, hexprint("step 1: blkno_buf",
1175 blkno_buf, blocksize));
1176
1177 /*
1178 * Compute an initial IV. All ciphers
1179 * can convert blkno_buf in-place.
1180 */
1181 iv = blkno_buf;
1182 ciprep(cs->sc_cdata.cf_priv, iv, blkno_buf, blocksize, dir);
1183 IFDEBUG(CGDB_CRYPTO, hexprint("step 2: iv", iv, blocksize));
1184
1185 cipher(cs->sc_cdata.cf_priv, &dstuio, &srcuio, iv, dir);
1186
1187 dst += todo;
1188 src += todo;
1189 blkno++;
1190 }
1191 }
1192
1193 #ifdef DEBUG
1194 static void
1195 hexprint(const char *start, void *buf, int len)
1196 {
1197 char *c = buf;
1198
1199 DIAGCONDPANIC(len < 0, ("hexprint: called with len < 0"));
1200 printf("%s: len=%06d 0x", start, len);
1201 while (len--)
1202 printf("%02x", (unsigned char) *c++);
1203 }
1204 #endif
1205
1206 static void
1207 selftest(void)
1208 {
1209 struct cgd_softc cs;
1210 void *buf;
1211
1212 printf("running cgd selftest ");
1213
1214 for (size_t i = 0; i < __arraycount(selftests); i++) {
1215 const char *alg = selftests[i].alg;
1216 const uint8_t *key = selftests[i].key;
1217 int keylen = selftests[i].keylen;
1218 int txtlen = selftests[i].txtlen;
1219
1220 printf("%s-%d ", alg, keylen);
1221
1222 memset(&cs, 0, sizeof(cs));
1223
1224 cs.sc_cfuncs = cryptfuncs_find(alg);
1225 if (cs.sc_cfuncs == NULL)
1226 panic("%s not implemented", alg);
1227
1228 cs.sc_cdata.cf_blocksize = 8 * selftests[i].blocksize;
1229 cs.sc_cdata.cf_mode = CGD_CIPHER_CBC_ENCBLKNO1;
1230 cs.sc_cdata.cf_keylen = keylen;
1231
1232 cs.sc_cdata.cf_priv = cs.sc_cfuncs->cf_init(keylen,
1233 key, &cs.sc_cdata.cf_blocksize);
1234 if (cs.sc_cdata.cf_priv == NULL)
1235 panic("cf_priv is NULL");
1236 if (cs.sc_cdata.cf_blocksize > CGD_MAXBLOCKSIZE)
1237 panic("bad block size %zu", cs.sc_cdata.cf_blocksize);
1238
1239 cs.sc_cdata.cf_blocksize /= 8;
1240
1241 buf = malloc(txtlen, M_DEVBUF, M_WAITOK);
1242 memcpy(buf, selftests[i].ptxt, txtlen);
1243
1244 cgd_cipher(&cs, buf, buf, txtlen, selftests[i].blkno,
1245 selftests[i].secsize, CGD_CIPHER_ENCRYPT);
1246 if (memcmp(buf, selftests[i].ctxt, txtlen) != 0)
1247 panic("encryption is broken");
1248
1249 cgd_cipher(&cs, buf, buf, txtlen, selftests[i].blkno,
1250 selftests[i].secsize, CGD_CIPHER_DECRYPT);
1251 if (memcmp(buf, selftests[i].ptxt, txtlen) != 0)
1252 panic("decryption is broken");
1253
1254 free(buf, M_DEVBUF);
1255 cs.sc_cfuncs->cf_destroy(cs.sc_cdata.cf_priv);
1256 }
1257
1258 printf("done\n");
1259 }
1260
1261 MODULE(MODULE_CLASS_DRIVER, cgd, "blowfish,des,dk_subr");
1262
1263 #ifdef _MODULE
1264 CFDRIVER_DECL(cgd, DV_DISK, NULL);
1265
1266 devmajor_t cgd_bmajor = -1, cgd_cmajor = -1;
1267 #endif
1268
1269 static int
1270 cgd_modcmd(modcmd_t cmd, void *arg)
1271 {
1272 int error = 0;
1273
1274 switch (cmd) {
1275 case MODULE_CMD_INIT:
1276 selftest();
1277 #ifdef _MODULE
1278 error = config_cfdriver_attach(&cgd_cd);
1279 if (error)
1280 break;
1281
1282 error = config_cfattach_attach(cgd_cd.cd_name, &cgd_ca);
1283 if (error) {
1284 config_cfdriver_detach(&cgd_cd);
1285 aprint_error("%s: unable to register cfattach for "
1286 "%s, error %d\n", __func__, cgd_cd.cd_name, error);
1287 break;
1288 }
1289 /*
1290 * Attach the {b,c}devsw's
1291 */
1292 error = devsw_attach("cgd", &cgd_bdevsw, &cgd_bmajor,
1293 &cgd_cdevsw, &cgd_cmajor);
1294
1295 /*
1296 * If devsw_attach fails, remove from autoconf database
1297 */
1298 if (error) {
1299 config_cfattach_detach(cgd_cd.cd_name, &cgd_ca);
1300 config_cfdriver_detach(&cgd_cd);
1301 aprint_error("%s: unable to attach %s devsw, "
1302 "error %d", __func__, cgd_cd.cd_name, error);
1303 break;
1304 }
1305 #endif
1306 break;
1307
1308 case MODULE_CMD_FINI:
1309 #ifdef _MODULE
1310 /*
1311 * Remove {b,c}devsw's
1312 */
1313 devsw_detach(&cgd_bdevsw, &cgd_cdevsw);
1314
1315 /*
1316 * Now remove device from autoconf database
1317 */
1318 error = config_cfattach_detach(cgd_cd.cd_name, &cgd_ca);
1319 if (error) {
1320 (void)devsw_attach("cgd", &cgd_bdevsw, &cgd_bmajor,
1321 &cgd_cdevsw, &cgd_cmajor);
1322 aprint_error("%s: failed to detach %s cfattach, "
1323 "error %d\n", __func__, cgd_cd.cd_name, error);
1324 break;
1325 }
1326 error = config_cfdriver_detach(&cgd_cd);
1327 if (error) {
1328 (void)config_cfattach_attach(cgd_cd.cd_name, &cgd_ca);
1329 (void)devsw_attach("cgd", &cgd_bdevsw, &cgd_bmajor,
1330 &cgd_cdevsw, &cgd_cmajor);
1331 aprint_error("%s: failed to detach %s cfdriver, "
1332 "error %d\n", __func__, cgd_cd.cd_name, error);
1333 break;
1334 }
1335 #endif
1336 break;
1337
1338 case MODULE_CMD_STAT:
1339 error = ENOTTY;
1340 break;
1341 default:
1342 error = ENOTTY;
1343 break;
1344 }
1345
1346 return error;
1347 }
1348