1 /* $NetBSD: cgd.c,v 1.142 2021/12/27 22:57:19 riastradh 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.142 2021/12/27 22:57:19 riastradh Exp $"); 34 35 #include <sys/types.h> 36 #include <sys/param.h> 37 #include <sys/buf.h> 38 #include <sys/bufq.h> 39 #include <sys/conf.h> 40 #include <sys/cpu.h> 41 #include <sys/device.h> 42 #include <sys/disk.h> 43 #include <sys/disklabel.h> 44 #include <sys/errno.h> 45 #include <sys/fcntl.h> 46 #include <sys/ioctl.h> 47 #include <sys/kmem.h> 48 #include <sys/module.h> 49 #include <sys/namei.h> /* for pathbuf */ 50 #include <sys/pool.h> 51 #include <sys/proc.h> 52 #include <sys/syslog.h> 53 #include <sys/systm.h> 54 #include <sys/vnode.h> 55 #include <sys/workqueue.h> 56 57 #include <dev/cgd_crypto.h> 58 #include <dev/cgdvar.h> 59 #include <dev/dkvar.h> 60 61 #include <miscfs/specfs/specdev.h> /* for v_rdev */ 62 63 #include "ioconf.h" 64 65 struct selftest_params { 66 const char *alg; 67 int encblkno8; 68 int blocksize; /* number of bytes */ 69 int secsize; 70 daddr_t blkno; 71 int keylen; /* number of bits */ 72 int txtlen; /* number of bytes */ 73 const uint8_t *key; 74 const uint8_t *ptxt; 75 const uint8_t *ctxt; 76 }; 77 78 /* Entry Point Functions */ 79 80 static dev_type_open(cgdopen); 81 static dev_type_close(cgdclose); 82 static dev_type_read(cgdread); 83 static dev_type_write(cgdwrite); 84 static dev_type_ioctl(cgdioctl); 85 static dev_type_strategy(cgdstrategy); 86 static dev_type_dump(cgddump); 87 static dev_type_size(cgdsize); 88 89 const struct bdevsw cgd_bdevsw = { 90 .d_open = cgdopen, 91 .d_close = cgdclose, 92 .d_strategy = cgdstrategy, 93 .d_ioctl = cgdioctl, 94 .d_dump = cgddump, 95 .d_psize = cgdsize, 96 .d_discard = nodiscard, 97 .d_flag = D_DISK | D_MPSAFE 98 }; 99 100 const struct cdevsw cgd_cdevsw = { 101 .d_open = cgdopen, 102 .d_close = cgdclose, 103 .d_read = cgdread, 104 .d_write = cgdwrite, 105 .d_ioctl = cgdioctl, 106 .d_stop = nostop, 107 .d_tty = notty, 108 .d_poll = nopoll, 109 .d_mmap = nommap, 110 .d_kqfilter = nokqfilter, 111 .d_discard = nodiscard, 112 .d_flag = D_DISK | D_MPSAFE 113 }; 114 115 /* 116 * Vector 5 from IEEE 1619/D16 truncated to 64 bytes, blkno 1. 117 */ 118 static const uint8_t selftest_aes_xts_256_ptxt[64] = { 119 0x27, 0xa7, 0x47, 0x9b, 0xef, 0xa1, 0xd4, 0x76, 120 0x48, 0x9f, 0x30, 0x8c, 0xd4, 0xcf, 0xa6, 0xe2, 121 0xa9, 0x6e, 0x4b, 0xbe, 0x32, 0x08, 0xff, 0x25, 122 0x28, 0x7d, 0xd3, 0x81, 0x96, 0x16, 0xe8, 0x9c, 123 0xc7, 0x8c, 0xf7, 0xf5, 0xe5, 0x43, 0x44, 0x5f, 124 0x83, 0x33, 0xd8, 0xfa, 0x7f, 0x56, 0x00, 0x00, 125 0x05, 0x27, 0x9f, 0xa5, 0xd8, 0xb5, 0xe4, 0xad, 126 0x40, 0xe7, 0x36, 0xdd, 0xb4, 0xd3, 0x54, 0x12, 127 }; 128 129 static const uint8_t selftest_aes_xts_256_ctxt[512] = { 130 0x26, 0x4d, 0x3c, 0xa8, 0x51, 0x21, 0x94, 0xfe, 131 0xc3, 0x12, 0xc8, 0xc9, 0x89, 0x1f, 0x27, 0x9f, 132 0xef, 0xdd, 0x60, 0x8d, 0x0c, 0x02, 0x7b, 0x60, 133 0x48, 0x3a, 0x3f, 0xa8, 0x11, 0xd6, 0x5e, 0xe5, 134 0x9d, 0x52, 0xd9, 0xe4, 0x0e, 0xc5, 0x67, 0x2d, 135 0x81, 0x53, 0x2b, 0x38, 0xb6, 0xb0, 0x89, 0xce, 136 0x95, 0x1f, 0x0f, 0x9c, 0x35, 0x59, 0x0b, 0x8b, 137 0x97, 0x8d, 0x17, 0x52, 0x13, 0xf3, 0x29, 0xbb, 138 }; 139 140 static const uint8_t selftest_aes_xts_256_key[33] = { 141 0x27, 0x18, 0x28, 0x18, 0x28, 0x45, 0x90, 0x45, 142 0x23, 0x53, 0x60, 0x28, 0x74, 0x71, 0x35, 0x26, 143 0x31, 0x41, 0x59, 0x26, 0x53, 0x58, 0x97, 0x93, 144 0x23, 0x84, 0x62, 0x64, 0x33, 0x83, 0x27, 0x95, 145 0 146 }; 147 148 /* 149 * Vector 11 from IEEE 1619/D16 truncated to 64 bytes, blkno 0xffff. 150 */ 151 static const uint8_t selftest_aes_xts_512_ptxt[64] = { 152 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 153 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 154 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 155 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 156 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 157 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 158 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 159 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 160 }; 161 162 static const uint8_t selftest_aes_xts_512_ctxt[64] = { 163 0x77, 0xa3, 0x12, 0x51, 0x61, 0x8a, 0x15, 0xe6, 164 0xb9, 0x2d, 0x1d, 0x66, 0xdf, 0xfe, 0x7b, 0x50, 165 0xb5, 0x0b, 0xad, 0x55, 0x23, 0x05, 0xba, 0x02, 166 0x17, 0xa6, 0x10, 0x68, 0x8e, 0xff, 0x7e, 0x11, 167 0xe1, 0xd0, 0x22, 0x54, 0x38, 0xe0, 0x93, 0x24, 168 0x2d, 0x6d, 0xb2, 0x74, 0xfd, 0xe8, 0x01, 0xd4, 169 0xca, 0xe0, 0x6f, 0x20, 0x92, 0xc7, 0x28, 0xb2, 170 0x47, 0x85, 0x59, 0xdf, 0x58, 0xe8, 0x37, 0xc2, 171 }; 172 173 static const uint8_t selftest_aes_xts_512_key[65] = { 174 0x27, 0x18, 0x28, 0x18, 0x28, 0x45, 0x90, 0x45, 175 0x23, 0x53, 0x60, 0x28, 0x74, 0x71, 0x35, 0x26, 176 0x62, 0x49, 0x77, 0x57, 0x24, 0x70, 0x93, 0x69, 177 0x99, 0x59, 0x57, 0x49, 0x66, 0x96, 0x76, 0x27, 178 0x31, 0x41, 0x59, 0x26, 0x53, 0x58, 0x97, 0x93, 179 0x23, 0x84, 0x62, 0x64, 0x33, 0x83, 0x27, 0x95, 180 0x02, 0x88, 0x41, 0x97, 0x16, 0x93, 0x99, 0x37, 181 0x51, 0x05, 0x82, 0x09, 0x74, 0x94, 0x45, 0x92, 182 0 183 }; 184 185 static const uint8_t selftest_aes_cbc_key[32] = { 186 0x27, 0x18, 0x28, 0x18, 0x28, 0x45, 0x90, 0x45, 187 0x23, 0x53, 0x60, 0x28, 0x74, 0x71, 0x35, 0x26, 188 0x62, 0x49, 0x77, 0x57, 0x24, 0x70, 0x93, 0x69, 189 0x99, 0x59, 0x57, 0x49, 0x66, 0x96, 0x76, 0x27, 190 }; 191 192 static const uint8_t selftest_aes_cbc_128_ptxt[64] = { 193 0x27, 0xa7, 0x47, 0x9b, 0xef, 0xa1, 0xd4, 0x76, 194 0x48, 0x9f, 0x30, 0x8c, 0xd4, 0xcf, 0xa6, 0xe2, 195 0xa9, 0x6e, 0x4b, 0xbe, 0x32, 0x08, 0xff, 0x25, 196 0x28, 0x7d, 0xd3, 0x81, 0x96, 0x16, 0xe8, 0x9c, 197 0xc7, 0x8c, 0xf7, 0xf5, 0xe5, 0x43, 0x44, 0x5f, 198 0x83, 0x33, 0xd8, 0xfa, 0x7f, 0x56, 0x00, 0x00, 199 0x05, 0x27, 0x9f, 0xa5, 0xd8, 0xb5, 0xe4, 0xad, 200 0x40, 0xe7, 0x36, 0xdd, 0xb4, 0xd3, 0x54, 0x12, 201 }; 202 203 static const uint8_t selftest_aes_cbc_128_ctxt[64] = { /* blkno=1 */ 204 0x93, 0x94, 0x56, 0x36, 0x83, 0xbc, 0xff, 0xa4, 205 0xe0, 0x24, 0x34, 0x12, 0xbe, 0xfa, 0xb0, 0x7d, 206 0x88, 0x1e, 0xc5, 0x57, 0x55, 0x23, 0x05, 0x0c, 207 0x69, 0xa5, 0xc1, 0xda, 0x64, 0xee, 0x74, 0x10, 208 0xc2, 0xc5, 0xe6, 0x66, 0xd6, 0xa7, 0x49, 0x1c, 209 0x9d, 0x40, 0xb5, 0x0c, 0x9b, 0x6e, 0x1c, 0xe6, 210 0xb1, 0x7a, 0x1c, 0xe7, 0x5a, 0xfe, 0xf9, 0x2a, 211 0x78, 0xfa, 0xb7, 0x7b, 0x08, 0xdf, 0x8e, 0x51, 212 }; 213 214 static const uint8_t selftest_aes_cbc_256_ptxt[64] = { 215 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 216 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 217 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 218 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 219 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 220 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 221 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 222 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 223 }; 224 225 static const uint8_t selftest_aes_cbc_256_ctxt[64] = { /* blkno=0xffff */ 226 0x6c, 0xa3, 0x15, 0x17, 0x51, 0x90, 0xe9, 0x69, 227 0x08, 0x36, 0x7b, 0xa6, 0xbb, 0xd1, 0x0b, 0x9e, 228 0xcd, 0x6b, 0x1e, 0xaf, 0xb6, 0x2e, 0x62, 0x7d, 229 0x8e, 0xde, 0xf0, 0xed, 0x0d, 0x44, 0xe7, 0x31, 230 0x26, 0xcf, 0xd5, 0x0b, 0x3e, 0x95, 0x59, 0x89, 231 0xdf, 0x5d, 0xd6, 0x9a, 0x00, 0x66, 0xcc, 0x7f, 232 0x45, 0xd3, 0x06, 0x58, 0xed, 0xef, 0x49, 0x47, 233 0x87, 0x89, 0x17, 0x7d, 0x08, 0x56, 0x50, 0xe1, 234 }; 235 236 static const uint8_t selftest_3des_cbc_key[24] = { 237 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 238 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 239 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 240 }; 241 242 static const uint8_t selftest_3des_cbc_ptxt[64] = { 243 0x27, 0xa7, 0x47, 0x9b, 0xef, 0xa1, 0xd4, 0x76, 244 0x48, 0x9f, 0x30, 0x8c, 0xd4, 0xcf, 0xa6, 0xe2, 245 0xa9, 0x6e, 0x4b, 0xbe, 0x32, 0x08, 0xff, 0x25, 246 0x28, 0x7d, 0xd3, 0x81, 0x96, 0x16, 0xe8, 0x9c, 247 0xc7, 0x8c, 0xf7, 0xf5, 0xe5, 0x43, 0x44, 0x5f, 248 0x83, 0x33, 0xd8, 0xfa, 0x7f, 0x56, 0x00, 0x00, 249 0x05, 0x27, 0x9f, 0xa5, 0xd8, 0xb5, 0xe4, 0xad, 250 0x40, 0xe7, 0x36, 0xdd, 0xb4, 0xd3, 0x54, 0x12, 251 }; 252 253 static const uint8_t selftest_3des_cbc_ctxt[64] = { 254 0xa2, 0xfe, 0x81, 0xaa, 0x10, 0x6c, 0xea, 0xb9, 255 0x11, 0x58, 0x1f, 0x29, 0xb5, 0x86, 0x71, 0x56, 256 0xe9, 0x25, 0x1d, 0x07, 0xb1, 0x69, 0x59, 0x6c, 257 0x96, 0x80, 0xf7, 0x54, 0x38, 0xaa, 0xa7, 0xe4, 258 0xe8, 0x81, 0xf5, 0x00, 0xbb, 0x1c, 0x00, 0x3c, 259 0xba, 0x38, 0x45, 0x97, 0x4c, 0xcf, 0x84, 0x14, 260 0x46, 0x86, 0xd9, 0xf4, 0xc5, 0xe2, 0xf0, 0x54, 261 0xde, 0x41, 0xf6, 0xa1, 0xef, 0x1b, 0x0a, 0xea, 262 }; 263 264 static const uint8_t selftest_bf_cbc_key[56] = { 265 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 266 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 267 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 268 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 269 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 270 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 271 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 272 }; 273 274 static const uint8_t selftest_bf_cbc_ptxt[64] = { 275 0x27, 0xa7, 0x47, 0x9b, 0xef, 0xa1, 0xd4, 0x76, 276 0x48, 0x9f, 0x30, 0x8c, 0xd4, 0xcf, 0xa6, 0xe2, 277 0xa9, 0x6e, 0x4b, 0xbe, 0x32, 0x08, 0xff, 0x25, 278 0x28, 0x7d, 0xd3, 0x81, 0x96, 0x16, 0xe8, 0x9c, 279 0xc7, 0x8c, 0xf7, 0xf5, 0xe5, 0x43, 0x44, 0x5f, 280 0x83, 0x33, 0xd8, 0xfa, 0x7f, 0x56, 0x00, 0x00, 281 0x05, 0x27, 0x9f, 0xa5, 0xd8, 0xb5, 0xe4, 0xad, 282 0x40, 0xe7, 0x36, 0xdd, 0xb4, 0xd3, 0x54, 0x12, 283 }; 284 285 static const uint8_t selftest_bf_cbc_ctxt[64] = { 286 0xec, 0xa2, 0xc0, 0x0e, 0xa9, 0x7f, 0x04, 0x1e, 287 0x2e, 0x4f, 0x64, 0x07, 0x67, 0x3e, 0xf4, 0x58, 288 0x61, 0x5f, 0xd3, 0x50, 0x5e, 0xd3, 0x4d, 0x34, 289 0xa0, 0x53, 0xbe, 0x47, 0x75, 0x69, 0x3b, 0x1f, 290 0x86, 0xf2, 0xae, 0x8b, 0xb7, 0x91, 0xda, 0xd4, 291 0x2b, 0xa5, 0x47, 0x9b, 0x7d, 0x13, 0x30, 0xdd, 292 0x7b, 0xad, 0x86, 0x57, 0x51, 0x11, 0x74, 0x42, 293 0xb8, 0xbf, 0x69, 0x17, 0x20, 0x0a, 0xf7, 0xda, 294 }; 295 296 static const uint8_t selftest_aes_cbc_encblkno8_zero64[64]; 297 static const uint8_t selftest_aes_cbc_encblkno8_ctxt[64] = { 298 0xa2, 0x06, 0x26, 0x26, 0xac, 0xdc, 0xe7, 0xcf, 299 0x47, 0x68, 0x24, 0x0e, 0xfa, 0x40, 0x44, 0x83, 300 0x07, 0xe1, 0xf4, 0x5d, 0x53, 0x47, 0xa0, 0xfe, 301 0xc0, 0x6e, 0x4e, 0xf8, 0x9d, 0x98, 0x63, 0xb8, 302 0x2c, 0x27, 0xfa, 0x3a, 0xd5, 0x40, 0xda, 0xdb, 303 0xe6, 0xc3, 0xe4, 0xfb, 0x85, 0x53, 0xfb, 0x78, 304 0x5d, 0xbd, 0x8f, 0x4c, 0x1a, 0x04, 0x9c, 0x88, 305 0x85, 0xec, 0x3c, 0x56, 0x46, 0x1a, 0x6e, 0xf5, 306 }; 307 308 const struct selftest_params selftests[] = { 309 { 310 .alg = "aes-xts", 311 .blocksize = 16, 312 .secsize = 512, 313 .blkno = 1, 314 .keylen = 256, 315 .txtlen = sizeof(selftest_aes_xts_256_ptxt), 316 .key = selftest_aes_xts_256_key, 317 .ptxt = selftest_aes_xts_256_ptxt, 318 .ctxt = selftest_aes_xts_256_ctxt 319 }, 320 { 321 .alg = "aes-xts", 322 .blocksize = 16, 323 .secsize = 512, 324 .blkno = 0xffff, 325 .keylen = 512, 326 .txtlen = sizeof(selftest_aes_xts_512_ptxt), 327 .key = selftest_aes_xts_512_key, 328 .ptxt = selftest_aes_xts_512_ptxt, 329 .ctxt = selftest_aes_xts_512_ctxt 330 }, 331 { 332 .alg = "aes-cbc", 333 .blocksize = 16, 334 .secsize = 512, 335 .blkno = 1, 336 .keylen = 128, 337 .txtlen = sizeof(selftest_aes_cbc_128_ptxt), 338 .key = selftest_aes_cbc_key, 339 .ptxt = selftest_aes_cbc_128_ptxt, 340 .ctxt = selftest_aes_cbc_128_ctxt, 341 }, 342 { 343 .alg = "aes-cbc", 344 .blocksize = 16, 345 .secsize = 512, 346 .blkno = 0xffff, 347 .keylen = 256, 348 .txtlen = sizeof(selftest_aes_cbc_256_ptxt), 349 .key = selftest_aes_cbc_key, 350 .ptxt = selftest_aes_cbc_256_ptxt, 351 .ctxt = selftest_aes_cbc_256_ctxt, 352 }, 353 { 354 .alg = "3des-cbc", 355 .blocksize = 8, 356 .secsize = 512, 357 .blkno = 1, 358 .keylen = 192, /* 168 + 3*8 parity bits */ 359 .txtlen = sizeof(selftest_3des_cbc_ptxt), 360 .key = selftest_3des_cbc_key, 361 .ptxt = selftest_3des_cbc_ptxt, 362 .ctxt = selftest_3des_cbc_ctxt, 363 }, 364 { 365 .alg = "blowfish-cbc", 366 .blocksize = 8, 367 .secsize = 512, 368 .blkno = 1, 369 .keylen = 448, 370 .txtlen = sizeof(selftest_bf_cbc_ptxt), 371 .key = selftest_bf_cbc_key, 372 .ptxt = selftest_bf_cbc_ptxt, 373 .ctxt = selftest_bf_cbc_ctxt, 374 }, 375 { 376 .alg = "aes-cbc", 377 .encblkno8 = 1, 378 .blocksize = 16, 379 .secsize = 512, 380 .blkno = 0, 381 .keylen = 128, 382 .txtlen = sizeof(selftest_aes_cbc_encblkno8_zero64), 383 .key = selftest_aes_cbc_encblkno8_zero64, 384 .ptxt = selftest_aes_cbc_encblkno8_zero64, 385 .ctxt = selftest_aes_cbc_encblkno8_ctxt, 386 }, 387 }; 388 389 static int cgd_match(device_t, cfdata_t, void *); 390 static void cgd_attach(device_t, device_t, void *); 391 static int cgd_detach(device_t, int); 392 static struct cgd_softc *cgd_spawn(int); 393 static struct cgd_worker *cgd_create_one_worker(void); 394 static void cgd_destroy_one_worker(struct cgd_worker *); 395 static struct cgd_worker *cgd_create_worker(void); 396 static void cgd_destroy_worker(struct cgd_worker *); 397 static int cgd_destroy(device_t); 398 399 /* Internal Functions */ 400 401 static int cgd_diskstart(device_t, struct buf *); 402 static void cgd_diskstart2(struct cgd_softc *, struct cgd_xfer *); 403 static void cgdiodone(struct buf *); 404 static void cgd_iodone2(struct cgd_softc *, struct cgd_xfer *); 405 static void cgd_enqueue(struct cgd_softc *, struct cgd_xfer *); 406 static void cgd_process(struct work *, void *); 407 static int cgd_dumpblocks(device_t, void *, daddr_t, int); 408 409 static int cgd_ioctl_set(struct cgd_softc *, void *, struct lwp *); 410 static int cgd_ioctl_clr(struct cgd_softc *, struct lwp *); 411 static int cgd_ioctl_get(dev_t, void *, struct lwp *); 412 static int cgdinit(struct cgd_softc *, const char *, struct vnode *, 413 struct lwp *); 414 static void cgd_cipher(struct cgd_softc *, void *, const void *, 415 size_t, daddr_t, size_t, int); 416 417 static void cgd_selftest(void); 418 419 static const struct dkdriver cgddkdriver = { 420 .d_minphys = minphys, 421 .d_open = cgdopen, 422 .d_close = cgdclose, 423 .d_strategy = cgdstrategy, 424 .d_iosize = NULL, 425 .d_diskstart = cgd_diskstart, 426 .d_dumpblocks = cgd_dumpblocks, 427 .d_lastclose = NULL 428 }; 429 430 CFATTACH_DECL3_NEW(cgd, sizeof(struct cgd_softc), 431 cgd_match, cgd_attach, cgd_detach, NULL, NULL, NULL, DVF_DETACH_SHUTDOWN); 432 433 /* DIAGNOSTIC and DEBUG definitions */ 434 435 #if defined(CGDDEBUG) && !defined(DEBUG) 436 #define DEBUG 437 #endif 438 439 #ifdef DEBUG 440 int cgddebug = 0; 441 442 #define CGDB_FOLLOW 0x1 443 #define CGDB_IO 0x2 444 #define CGDB_CRYPTO 0x4 445 446 #define IFDEBUG(x,y) if (cgddebug & (x)) y 447 #define DPRINTF(x,y) IFDEBUG(x, printf y) 448 #define DPRINTF_FOLLOW(y) DPRINTF(CGDB_FOLLOW, y) 449 450 static void hexprint(const char *, void *, int); 451 452 #else 453 #define IFDEBUG(x,y) 454 #define DPRINTF(x,y) 455 #define DPRINTF_FOLLOW(y) 456 #endif 457 458 /* Global variables */ 459 460 static kmutex_t cgd_spawning_mtx; 461 static kcondvar_t cgd_spawning_cv; 462 static bool cgd_spawning; 463 static struct cgd_worker *cgd_worker; 464 static u_int cgd_refcnt; /* number of users of cgd_worker */ 465 466 /* Utility Functions */ 467 468 #define CGDUNIT(x) DISKUNIT(x) 469 470 /* The code */ 471 472 static int 473 cgd_lock(bool intr) 474 { 475 int error = 0; 476 477 mutex_enter(&cgd_spawning_mtx); 478 while (cgd_spawning) { 479 if (intr) 480 error = cv_wait_sig(&cgd_spawning_cv, &cgd_spawning_mtx); 481 else 482 cv_wait(&cgd_spawning_cv, &cgd_spawning_mtx); 483 } 484 if (error == 0) 485 cgd_spawning = true; 486 mutex_exit(&cgd_spawning_mtx); 487 return error; 488 } 489 490 static void 491 cgd_unlock(void) 492 { 493 mutex_enter(&cgd_spawning_mtx); 494 cgd_spawning = false; 495 cv_broadcast(&cgd_spawning_cv); 496 mutex_exit(&cgd_spawning_mtx); 497 } 498 499 static struct cgd_softc * 500 getcgd_softc(dev_t dev) 501 { 502 return device_lookup_private(&cgd_cd, CGDUNIT(dev)); 503 } 504 505 static int 506 cgd_match(device_t self, cfdata_t cfdata, void *aux) 507 { 508 509 return 1; 510 } 511 512 static void 513 cgd_attach(device_t parent, device_t self, void *aux) 514 { 515 struct cgd_softc *sc = device_private(self); 516 517 mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_BIO); 518 cv_init(&sc->sc_cv, "cgdcv"); 519 dk_init(&sc->sc_dksc, self, DKTYPE_CGD); 520 disk_init(&sc->sc_dksc.sc_dkdev, sc->sc_dksc.sc_xname, &cgddkdriver); 521 522 if (!pmf_device_register(self, NULL, NULL)) 523 aprint_error_dev(self, 524 "unable to register power management hooks\n"); 525 } 526 527 528 static int 529 cgd_detach(device_t self, int flags) 530 { 531 int ret; 532 struct cgd_softc *sc = device_private(self); 533 struct dk_softc *dksc = &sc->sc_dksc; 534 535 if (DK_BUSY(dksc, 0)) 536 return EBUSY; 537 538 if (DK_ATTACHED(dksc) && 539 (ret = cgd_ioctl_clr(sc, curlwp)) != 0) 540 return ret; 541 542 disk_destroy(&dksc->sc_dkdev); 543 cv_destroy(&sc->sc_cv); 544 mutex_destroy(&sc->sc_lock); 545 546 return 0; 547 } 548 549 void 550 cgdattach(int num) 551 { 552 #ifndef _MODULE 553 int error; 554 555 mutex_init(&cgd_spawning_mtx, MUTEX_DEFAULT, IPL_NONE); 556 cv_init(&cgd_spawning_cv, "cgspwn"); 557 558 error = config_cfattach_attach(cgd_cd.cd_name, &cgd_ca); 559 if (error != 0) 560 aprint_error("%s: unable to register cfattach\n", 561 cgd_cd.cd_name); 562 #endif 563 564 cgd_selftest(); 565 } 566 567 static struct cgd_softc * 568 cgd_spawn(int unit) 569 { 570 cfdata_t cf; 571 struct cgd_worker *cw; 572 struct cgd_softc *sc; 573 574 cf = kmem_alloc(sizeof(*cf), KM_SLEEP); 575 cf->cf_name = cgd_cd.cd_name; 576 cf->cf_atname = cgd_cd.cd_name; 577 cf->cf_unit = unit; 578 cf->cf_fstate = FSTATE_STAR; 579 580 cw = cgd_create_one_worker(); 581 if (cw == NULL) { 582 kmem_free(cf, sizeof(*cf)); 583 return NULL; 584 } 585 586 sc = device_private(config_attach_pseudo(cf)); 587 if (sc == NULL) { 588 cgd_destroy_one_worker(cw); 589 return NULL; 590 } 591 592 sc->sc_worker = cw; 593 594 return sc; 595 } 596 597 static int 598 cgd_destroy(device_t dev) 599 { 600 struct cgd_softc *sc = device_private(dev); 601 struct cgd_worker *cw = sc->sc_worker; 602 cfdata_t cf; 603 int error; 604 605 cf = device_cfdata(dev); 606 error = config_detach(dev, DETACH_QUIET); 607 if (error) 608 return error; 609 610 cgd_destroy_one_worker(cw); 611 612 kmem_free(cf, sizeof(*cf)); 613 return 0; 614 } 615 616 static void 617 cgd_busy(struct cgd_softc *sc) 618 { 619 620 mutex_enter(&sc->sc_lock); 621 while (sc->sc_busy) 622 cv_wait(&sc->sc_cv, &sc->sc_lock); 623 sc->sc_busy = true; 624 mutex_exit(&sc->sc_lock); 625 } 626 627 static void 628 cgd_unbusy(struct cgd_softc *sc) 629 { 630 631 mutex_enter(&sc->sc_lock); 632 sc->sc_busy = false; 633 cv_broadcast(&sc->sc_cv); 634 mutex_exit(&sc->sc_lock); 635 } 636 637 static struct cgd_worker * 638 cgd_create_one_worker(void) 639 { 640 KASSERT(cgd_spawning); 641 642 if (cgd_refcnt++ == 0) { 643 KASSERT(cgd_worker == NULL); 644 cgd_worker = cgd_create_worker(); 645 } 646 647 KASSERT(cgd_worker != NULL); 648 return cgd_worker; 649 } 650 651 static void 652 cgd_destroy_one_worker(struct cgd_worker *cw) 653 { 654 KASSERT(cgd_spawning); 655 KASSERT(cw == cgd_worker); 656 657 if (--cgd_refcnt == 0) { 658 cgd_destroy_worker(cgd_worker); 659 cgd_worker = NULL; 660 } 661 } 662 663 static struct cgd_worker * 664 cgd_create_worker(void) 665 { 666 struct cgd_worker *cw; 667 struct workqueue *wq; 668 struct pool *cp; 669 int error; 670 671 cw = kmem_alloc(sizeof(struct cgd_worker), KM_SLEEP); 672 cp = kmem_alloc(sizeof(struct pool), KM_SLEEP); 673 674 error = workqueue_create(&wq, "cgd", cgd_process, NULL, 675 PRI_BIO, IPL_BIO, WQ_FPU|WQ_MPSAFE|WQ_PERCPU); 676 if (error) { 677 kmem_free(cp, sizeof(struct pool)); 678 kmem_free(cw, sizeof(struct cgd_worker)); 679 return NULL; 680 } 681 682 cw->cw_cpool = cp; 683 cw->cw_wq = wq; 684 pool_init(cw->cw_cpool, sizeof(struct cgd_xfer), 0, 685 0, 0, "cgdcpl", NULL, IPL_BIO); 686 mutex_init(&cw->cw_lock, MUTEX_DEFAULT, IPL_BIO); 687 688 return cw; 689 } 690 691 static void 692 cgd_destroy_worker(struct cgd_worker *cw) 693 { 694 695 /* 696 * Wait for all worker threads to complete before destroying 697 * the rest of the cgd_worker. 698 */ 699 if (cw->cw_wq) 700 workqueue_destroy(cw->cw_wq); 701 702 mutex_destroy(&cw->cw_lock); 703 704 if (cw->cw_cpool) { 705 pool_destroy(cw->cw_cpool); 706 kmem_free(cw->cw_cpool, sizeof(struct pool)); 707 } 708 709 kmem_free(cw, sizeof(struct cgd_worker)); 710 } 711 712 static int 713 cgdopen(dev_t dev, int flags, int fmt, struct lwp *l) 714 { 715 struct cgd_softc *sc; 716 int error; 717 718 DPRINTF_FOLLOW(("cgdopen(0x%"PRIx64", %d)\n", dev, flags)); 719 720 error = cgd_lock(true); 721 if (error) 722 return error; 723 sc = getcgd_softc(dev); 724 if (sc == NULL) 725 sc = cgd_spawn(CGDUNIT(dev)); 726 cgd_unlock(); 727 if (sc == NULL) 728 return ENXIO; 729 730 return dk_open(&sc->sc_dksc, dev, flags, fmt, l); 731 } 732 733 static int 734 cgdclose(dev_t dev, int flags, int fmt, struct lwp *l) 735 { 736 struct cgd_softc *sc; 737 struct dk_softc *dksc; 738 int error; 739 740 DPRINTF_FOLLOW(("cgdclose(0x%"PRIx64", %d)\n", dev, flags)); 741 742 error = cgd_lock(false); 743 if (error) 744 return error; 745 sc = getcgd_softc(dev); 746 if (sc == NULL) { 747 error = ENXIO; 748 goto done; 749 } 750 751 dksc = &sc->sc_dksc; 752 if ((error = dk_close(dksc, dev, flags, fmt, l)) != 0) 753 goto done; 754 755 if (!DK_ATTACHED(dksc)) { 756 if ((error = cgd_destroy(sc->sc_dksc.sc_dev)) != 0) { 757 device_printf(dksc->sc_dev, 758 "unable to detach instance\n"); 759 goto done; 760 } 761 } 762 763 done: 764 cgd_unlock(); 765 766 return error; 767 } 768 769 static void 770 cgdstrategy(struct buf *bp) 771 { 772 struct cgd_softc *sc = getcgd_softc(bp->b_dev); 773 774 DPRINTF_FOLLOW(("cgdstrategy(%p): b_bcount = %ld\n", bp, 775 (long)bp->b_bcount)); 776 777 /* 778 * Reject unaligned writes. 779 */ 780 if (((uintptr_t)bp->b_data & 3) != 0) { 781 bp->b_error = EINVAL; 782 goto bail; 783 } 784 785 dk_strategy(&sc->sc_dksc, bp); 786 return; 787 788 bail: 789 bp->b_resid = bp->b_bcount; 790 biodone(bp); 791 return; 792 } 793 794 static int 795 cgdsize(dev_t dev) 796 { 797 struct cgd_softc *sc = getcgd_softc(dev); 798 799 DPRINTF_FOLLOW(("cgdsize(0x%"PRIx64")\n", dev)); 800 if (!sc) 801 return -1; 802 return dk_size(&sc->sc_dksc, dev); 803 } 804 805 /* 806 * cgd_{get,put}data are functions that deal with getting a buffer 807 * for the new encrypted data. 808 * We can no longer have a buffer per device, we need a buffer per 809 * work queue... 810 */ 811 812 static void * 813 cgd_getdata(struct cgd_softc *sc, unsigned long size) 814 { 815 void *data = NULL; 816 817 mutex_enter(&sc->sc_lock); 818 if (!sc->sc_data_used) { 819 sc->sc_data_used = true; 820 data = sc->sc_data; 821 } 822 mutex_exit(&sc->sc_lock); 823 824 if (data) 825 return data; 826 827 return kmem_intr_alloc(size, KM_NOSLEEP); 828 } 829 830 static void 831 cgd_putdata(struct cgd_softc *sc, void *data, unsigned long size) 832 { 833 834 if (data == sc->sc_data) { 835 mutex_enter(&sc->sc_lock); 836 sc->sc_data_used = false; 837 mutex_exit(&sc->sc_lock); 838 } else 839 kmem_intr_free(data, size); 840 } 841 842 static int 843 cgd_diskstart(device_t dev, struct buf *bp) 844 { 845 struct cgd_softc *sc = device_private(dev); 846 struct cgd_worker *cw = sc->sc_worker; 847 struct dk_softc *dksc = &sc->sc_dksc; 848 struct disk_geom *dg = &dksc->sc_dkdev.dk_geom; 849 struct cgd_xfer *cx; 850 struct buf *nbp; 851 void * newaddr; 852 daddr_t bn; 853 854 DPRINTF_FOLLOW(("cgd_diskstart(%p, %p)\n", dksc, bp)); 855 856 bn = bp->b_rawblkno; 857 858 /* 859 * We attempt to allocate all of our resources up front, so that 860 * we can fail quickly if they are unavailable. 861 */ 862 nbp = getiobuf(sc->sc_tvn, false); 863 if (nbp == NULL) 864 return EAGAIN; 865 866 cx = pool_get(cw->cw_cpool, PR_NOWAIT); 867 if (cx == NULL) { 868 putiobuf(nbp); 869 return EAGAIN; 870 } 871 872 cx->cx_sc = sc; 873 cx->cx_obp = bp; 874 cx->cx_nbp = nbp; 875 cx->cx_srcv = cx->cx_dstv = bp->b_data; 876 cx->cx_blkno = bn; 877 cx->cx_secsize = dg->dg_secsize; 878 879 /* 880 * If we are writing, then we need to encrypt the outgoing 881 * block into a new block of memory. 882 */ 883 if ((bp->b_flags & B_READ) == 0) { 884 newaddr = cgd_getdata(sc, bp->b_bcount); 885 if (!newaddr) { 886 pool_put(cw->cw_cpool, cx); 887 putiobuf(nbp); 888 return EAGAIN; 889 } 890 891 cx->cx_dstv = newaddr; 892 cx->cx_len = bp->b_bcount; 893 cx->cx_dir = CGD_CIPHER_ENCRYPT; 894 895 cgd_enqueue(sc, cx); 896 return 0; 897 } 898 899 cgd_diskstart2(sc, cx); 900 return 0; 901 } 902 903 static void 904 cgd_diskstart2(struct cgd_softc *sc, struct cgd_xfer *cx) 905 { 906 struct vnode *vp; 907 struct buf *bp; 908 struct buf *nbp; 909 910 bp = cx->cx_obp; 911 nbp = cx->cx_nbp; 912 913 nbp->b_data = cx->cx_dstv; 914 nbp->b_flags = bp->b_flags; 915 nbp->b_oflags = bp->b_oflags; 916 nbp->b_cflags = bp->b_cflags; 917 nbp->b_iodone = cgdiodone; 918 nbp->b_proc = bp->b_proc; 919 nbp->b_blkno = btodb(cx->cx_blkno * cx->cx_secsize); 920 nbp->b_bcount = bp->b_bcount; 921 nbp->b_private = cx; 922 923 BIO_COPYPRIO(nbp, bp); 924 925 if ((nbp->b_flags & B_READ) == 0) { 926 vp = nbp->b_vp; 927 mutex_enter(vp->v_interlock); 928 vp->v_numoutput++; 929 mutex_exit(vp->v_interlock); 930 } 931 VOP_STRATEGY(sc->sc_tvn, nbp); 932 } 933 934 static void 935 cgdiodone(struct buf *nbp) 936 { 937 struct cgd_xfer *cx = nbp->b_private; 938 struct buf *obp = cx->cx_obp; 939 struct cgd_softc *sc = getcgd_softc(obp->b_dev); 940 struct dk_softc *dksc = &sc->sc_dksc; 941 struct disk_geom *dg = &dksc->sc_dkdev.dk_geom; 942 daddr_t bn; 943 944 KDASSERT(sc); 945 946 DPRINTF_FOLLOW(("cgdiodone(%p)\n", nbp)); 947 DPRINTF(CGDB_IO, ("cgdiodone: bp %p bcount %d resid %d\n", 948 obp, obp->b_bcount, obp->b_resid)); 949 DPRINTF(CGDB_IO, (" dev 0x%"PRIx64", nbp %p bn %" PRId64 950 " addr %p bcnt %d\n", nbp->b_dev, nbp, nbp->b_blkno, nbp->b_data, 951 nbp->b_bcount)); 952 if (nbp->b_error != 0) { 953 obp->b_error = nbp->b_error; 954 DPRINTF(CGDB_IO, ("%s: error %d\n", dksc->sc_xname, 955 obp->b_error)); 956 } 957 958 /* Perform the decryption if we are reading. 959 * 960 * Note: use the blocknumber from nbp, since it is what 961 * we used to encrypt the blocks. 962 */ 963 964 if (nbp->b_flags & B_READ) { 965 bn = dbtob(nbp->b_blkno) / dg->dg_secsize; 966 967 cx->cx_obp = obp; 968 cx->cx_nbp = nbp; 969 cx->cx_dstv = obp->b_data; 970 cx->cx_srcv = obp->b_data; 971 cx->cx_len = obp->b_bcount; 972 cx->cx_blkno = bn; 973 cx->cx_secsize = dg->dg_secsize; 974 cx->cx_dir = CGD_CIPHER_DECRYPT; 975 976 cgd_enqueue(sc, cx); 977 return; 978 } 979 980 cgd_iodone2(sc, cx); 981 } 982 983 static void 984 cgd_iodone2(struct cgd_softc *sc, struct cgd_xfer *cx) 985 { 986 struct cgd_worker *cw = sc->sc_worker; 987 struct buf *obp = cx->cx_obp; 988 struct buf *nbp = cx->cx_nbp; 989 struct dk_softc *dksc = &sc->sc_dksc; 990 991 pool_put(cw->cw_cpool, cx); 992 993 /* If we allocated memory, free it now... */ 994 if (nbp->b_data != obp->b_data) 995 cgd_putdata(sc, nbp->b_data, nbp->b_bcount); 996 997 putiobuf(nbp); 998 999 /* Request is complete for whatever reason */ 1000 obp->b_resid = 0; 1001 if (obp->b_error != 0) 1002 obp->b_resid = obp->b_bcount; 1003 1004 dk_done(dksc, obp); 1005 dk_start(dksc, NULL); 1006 } 1007 1008 static int 1009 cgd_dumpblocks(device_t dev, void *va, daddr_t blkno, int nblk) 1010 { 1011 struct cgd_softc *sc = device_private(dev); 1012 struct dk_softc *dksc = &sc->sc_dksc; 1013 struct disk_geom *dg = &dksc->sc_dkdev.dk_geom; 1014 size_t nbytes, blksize; 1015 void *buf; 1016 int error; 1017 1018 /* 1019 * dk_dump gives us units of disklabel sectors. Everything 1020 * else in cgd uses units of diskgeom sectors. These had 1021 * better agree; otherwise we need to figure out how to convert 1022 * between them. 1023 */ 1024 KASSERTMSG((dg->dg_secsize == dksc->sc_dkdev.dk_label->d_secsize), 1025 "diskgeom secsize %"PRIu32" != disklabel secsize %"PRIu32, 1026 dg->dg_secsize, dksc->sc_dkdev.dk_label->d_secsize); 1027 blksize = dg->dg_secsize; 1028 1029 /* 1030 * Compute the number of bytes in this request, which dk_dump 1031 * has `helpfully' converted to a number of blocks for us. 1032 */ 1033 nbytes = nblk*blksize; 1034 1035 /* Try to acquire a buffer to store the ciphertext. */ 1036 buf = cgd_getdata(sc, nbytes); 1037 if (buf == NULL) 1038 /* Out of memory: give up. */ 1039 return ENOMEM; 1040 1041 /* Encrypt the caller's data into the temporary buffer. */ 1042 cgd_cipher(sc, buf, va, nbytes, blkno, blksize, CGD_CIPHER_ENCRYPT); 1043 1044 /* Pass it on to the underlying disk device. */ 1045 error = bdev_dump(sc->sc_tdev, blkno, buf, nbytes); 1046 1047 /* Release the buffer. */ 1048 cgd_putdata(sc, buf, nbytes); 1049 1050 /* Return any error from the underlying disk device. */ 1051 return error; 1052 } 1053 1054 /* XXX: we should probably put these into dksubr.c, mostly */ 1055 static int 1056 cgdread(dev_t dev, struct uio *uio, int flags) 1057 { 1058 struct cgd_softc *sc; 1059 struct dk_softc *dksc; 1060 1061 DPRINTF_FOLLOW(("cgdread(0x%llx, %p, %d)\n", 1062 (unsigned long long)dev, uio, flags)); 1063 sc = getcgd_softc(dev); 1064 if (sc == NULL) 1065 return ENXIO; 1066 dksc = &sc->sc_dksc; 1067 if (!DK_ATTACHED(dksc)) 1068 return ENXIO; 1069 return physio(cgdstrategy, NULL, dev, B_READ, minphys, uio); 1070 } 1071 1072 /* XXX: we should probably put these into dksubr.c, mostly */ 1073 static int 1074 cgdwrite(dev_t dev, struct uio *uio, int flags) 1075 { 1076 struct cgd_softc *sc; 1077 struct dk_softc *dksc; 1078 1079 DPRINTF_FOLLOW(("cgdwrite(0x%"PRIx64", %p, %d)\n", dev, uio, flags)); 1080 sc = getcgd_softc(dev); 1081 if (sc == NULL) 1082 return ENXIO; 1083 dksc = &sc->sc_dksc; 1084 if (!DK_ATTACHED(dksc)) 1085 return ENXIO; 1086 return physio(cgdstrategy, NULL, dev, B_WRITE, minphys, uio); 1087 } 1088 1089 static int 1090 cgdioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l) 1091 { 1092 struct cgd_softc *sc; 1093 struct dk_softc *dksc; 1094 int part = DISKPART(dev); 1095 int pmask = 1 << part; 1096 int error; 1097 1098 DPRINTF_FOLLOW(("cgdioctl(0x%"PRIx64", %ld, %p, %d, %p)\n", 1099 dev, cmd, data, flag, l)); 1100 1101 switch (cmd) { 1102 case CGDIOCGET: 1103 return cgd_ioctl_get(dev, data, l); 1104 case CGDIOCSET: 1105 case CGDIOCCLR: 1106 if ((flag & FWRITE) == 0) 1107 return EBADF; 1108 /* FALLTHROUGH */ 1109 default: 1110 sc = getcgd_softc(dev); 1111 if (sc == NULL) 1112 return ENXIO; 1113 dksc = &sc->sc_dksc; 1114 break; 1115 } 1116 1117 switch (cmd) { 1118 case CGDIOCSET: 1119 cgd_busy(sc); 1120 if (DK_ATTACHED(dksc)) 1121 error = EBUSY; 1122 else 1123 error = cgd_ioctl_set(sc, data, l); 1124 cgd_unbusy(sc); 1125 break; 1126 case CGDIOCCLR: 1127 cgd_busy(sc); 1128 if (DK_BUSY(&sc->sc_dksc, pmask)) 1129 error = EBUSY; 1130 else 1131 error = cgd_ioctl_clr(sc, l); 1132 cgd_unbusy(sc); 1133 break; 1134 case DIOCGCACHE: 1135 case DIOCCACHESYNC: 1136 cgd_busy(sc); 1137 if (!DK_ATTACHED(dksc)) { 1138 cgd_unbusy(sc); 1139 error = ENOENT; 1140 break; 1141 } 1142 /* 1143 * We pass this call down to the underlying disk. 1144 */ 1145 error = VOP_IOCTL(sc->sc_tvn, cmd, data, flag, l->l_cred); 1146 cgd_unbusy(sc); 1147 break; 1148 case DIOCGSECTORALIGN: { 1149 struct disk_sectoralign *dsa = data; 1150 1151 cgd_busy(sc); 1152 if (!DK_ATTACHED(dksc)) { 1153 cgd_unbusy(sc); 1154 error = ENOENT; 1155 break; 1156 } 1157 1158 /* Get the underlying disk's sector alignment. */ 1159 error = VOP_IOCTL(sc->sc_tvn, cmd, data, flag, l->l_cred); 1160 if (error) { 1161 cgd_unbusy(sc); 1162 break; 1163 } 1164 1165 /* Adjust for the disklabel partition if necessary. */ 1166 if (part != RAW_PART) { 1167 struct disklabel *lp = dksc->sc_dkdev.dk_label; 1168 daddr_t offset = lp->d_partitions[part].p_offset; 1169 uint32_t r = offset % dsa->dsa_alignment; 1170 1171 if (r < dsa->dsa_firstaligned) 1172 dsa->dsa_firstaligned = dsa->dsa_firstaligned 1173 - r; 1174 else 1175 dsa->dsa_firstaligned = (dsa->dsa_firstaligned 1176 + dsa->dsa_alignment) - r; 1177 } 1178 cgd_unbusy(sc); 1179 break; 1180 } 1181 case DIOCGSTRATEGY: 1182 case DIOCSSTRATEGY: 1183 if (!DK_ATTACHED(dksc)) { 1184 error = ENOENT; 1185 break; 1186 } 1187 /*FALLTHROUGH*/ 1188 default: 1189 error = dk_ioctl(dksc, dev, cmd, data, flag, l); 1190 break; 1191 case CGDIOCGET: 1192 KASSERT(0); 1193 error = EINVAL; 1194 } 1195 1196 return error; 1197 } 1198 1199 static int 1200 cgddump(dev_t dev, daddr_t blkno, void *va, size_t size) 1201 { 1202 struct cgd_softc *sc; 1203 1204 DPRINTF_FOLLOW(("cgddump(0x%"PRIx64", %" PRId64 ", %p, %lu)\n", 1205 dev, blkno, va, (unsigned long)size)); 1206 sc = getcgd_softc(dev); 1207 if (sc == NULL) 1208 return ENXIO; 1209 return dk_dump(&sc->sc_dksc, dev, blkno, va, size, DK_DUMP_RECURSIVE); 1210 } 1211 1212 /* 1213 * XXXrcd: 1214 * for now we hardcode the maximum key length. 1215 */ 1216 #define MAX_KEYSIZE 1024 1217 1218 static const struct { 1219 const char *n; 1220 int v; 1221 int d; 1222 } encblkno[] = { 1223 { "encblkno", CGD_CIPHER_CBC_ENCBLKNO8, 1 }, 1224 { "encblkno8", CGD_CIPHER_CBC_ENCBLKNO8, 1 }, 1225 { "encblkno1", CGD_CIPHER_CBC_ENCBLKNO1, 8 }, 1226 }; 1227 1228 /* ARGSUSED */ 1229 static int 1230 cgd_ioctl_set(struct cgd_softc *sc, void *data, struct lwp *l) 1231 { 1232 struct cgd_ioctl *ci = data; 1233 struct vnode *vp; 1234 int ret; 1235 size_t i; 1236 size_t keybytes; /* key length in bytes */ 1237 const char *cp; 1238 struct pathbuf *pb; 1239 char *inbuf; 1240 struct dk_softc *dksc = &sc->sc_dksc; 1241 1242 cp = ci->ci_disk; 1243 1244 ret = pathbuf_copyin(ci->ci_disk, &pb); 1245 if (ret != 0) { 1246 return ret; 1247 } 1248 ret = vn_bdev_openpath(pb, &vp, l); 1249 pathbuf_destroy(pb); 1250 if (ret != 0) { 1251 return ret; 1252 } 1253 1254 inbuf = kmem_alloc(MAX_KEYSIZE, KM_SLEEP); 1255 1256 if ((ret = cgdinit(sc, cp, vp, l)) != 0) 1257 goto bail; 1258 1259 (void)memset(inbuf, 0, MAX_KEYSIZE); 1260 ret = copyinstr(ci->ci_alg, inbuf, 256, NULL); 1261 if (ret) 1262 goto bail; 1263 sc->sc_cfuncs = cryptfuncs_find(inbuf); 1264 if (!sc->sc_cfuncs) { 1265 ret = EINVAL; 1266 goto bail; 1267 } 1268 1269 (void)memset(inbuf, 0, MAX_KEYSIZE); 1270 ret = copyinstr(ci->ci_ivmethod, inbuf, MAX_KEYSIZE, NULL); 1271 if (ret) 1272 goto bail; 1273 1274 for (i = 0; i < __arraycount(encblkno); i++) 1275 if (strcmp(encblkno[i].n, inbuf) == 0) 1276 break; 1277 1278 if (i == __arraycount(encblkno)) { 1279 ret = EINVAL; 1280 goto bail; 1281 } 1282 1283 keybytes = ci->ci_keylen / 8 + 1; 1284 if (keybytes > MAX_KEYSIZE) { 1285 ret = EINVAL; 1286 goto bail; 1287 } 1288 1289 (void)memset(inbuf, 0, MAX_KEYSIZE); 1290 ret = copyin(ci->ci_key, inbuf, keybytes); 1291 if (ret) 1292 goto bail; 1293 1294 sc->sc_cdata.cf_blocksize = ci->ci_blocksize; 1295 sc->sc_cdata.cf_mode = encblkno[i].v; 1296 1297 /* 1298 * Print a warning if the user selected the legacy encblkno8 1299 * mistake, and reject it altogether for ciphers that it 1300 * doesn't apply to. 1301 */ 1302 if (encblkno[i].v != CGD_CIPHER_CBC_ENCBLKNO1) { 1303 if (strcmp(sc->sc_cfuncs->cf_name, "aes-cbc") && 1304 strcmp(sc->sc_cfuncs->cf_name, "3des-cbc") && 1305 strcmp(sc->sc_cfuncs->cf_name, "blowfish-cbc")) { 1306 log(LOG_WARNING, "cgd: %s only makes sense for cbc," 1307 " not for %s; ignoring\n", 1308 encblkno[i].n, sc->sc_cfuncs->cf_name); 1309 sc->sc_cdata.cf_mode = CGD_CIPHER_CBC_ENCBLKNO1; 1310 } else { 1311 log(LOG_WARNING, "cgd: enabling legacy encblkno8\n"); 1312 } 1313 } 1314 1315 sc->sc_cdata.cf_keylen = ci->ci_keylen; 1316 sc->sc_cdata.cf_priv = sc->sc_cfuncs->cf_init(ci->ci_keylen, inbuf, 1317 &sc->sc_cdata.cf_blocksize); 1318 if (sc->sc_cdata.cf_blocksize > CGD_MAXBLOCKSIZE) { 1319 log(LOG_WARNING, "cgd: Disallowed cipher with blocksize %zu > %u\n", 1320 sc->sc_cdata.cf_blocksize, CGD_MAXBLOCKSIZE); 1321 sc->sc_cdata.cf_priv = NULL; 1322 } 1323 1324 /* 1325 * The blocksize is supposed to be in bytes. Unfortunately originally 1326 * it was expressed in bits. For compatibility we maintain encblkno 1327 * and encblkno8. 1328 */ 1329 sc->sc_cdata.cf_blocksize /= encblkno[i].d; 1330 (void)explicit_memset(inbuf, 0, MAX_KEYSIZE); 1331 if (!sc->sc_cdata.cf_priv) { 1332 ret = EINVAL; /* XXX is this the right error? */ 1333 goto bail; 1334 } 1335 kmem_free(inbuf, MAX_KEYSIZE); 1336 1337 bufq_alloc(&dksc->sc_bufq, "fcfs", 0); 1338 1339 sc->sc_data = kmem_alloc(MAXPHYS, KM_SLEEP); 1340 sc->sc_data_used = false; 1341 1342 /* Attach the disk. */ 1343 dk_attach(dksc); 1344 disk_attach(&dksc->sc_dkdev); 1345 1346 disk_set_info(dksc->sc_dev, &dksc->sc_dkdev, NULL); 1347 1348 /* Discover wedges on this disk. */ 1349 dkwedge_discover(&dksc->sc_dkdev); 1350 1351 return 0; 1352 1353 bail: 1354 kmem_free(inbuf, MAX_KEYSIZE); 1355 (void)vn_close(vp, FREAD|FWRITE, l->l_cred); 1356 return ret; 1357 } 1358 1359 /* ARGSUSED */ 1360 static int 1361 cgd_ioctl_clr(struct cgd_softc *sc, struct lwp *l) 1362 { 1363 struct dk_softc *dksc = &sc->sc_dksc; 1364 1365 if (!DK_ATTACHED(dksc)) 1366 return ENXIO; 1367 1368 /* Delete all of our wedges. */ 1369 dkwedge_delall(&dksc->sc_dkdev); 1370 1371 /* Kill off any queued buffers. */ 1372 dk_drain(dksc); 1373 bufq_free(dksc->sc_bufq); 1374 1375 (void)vn_close(sc->sc_tvn, FREAD|FWRITE, l->l_cred); 1376 sc->sc_cfuncs->cf_destroy(sc->sc_cdata.cf_priv); 1377 kmem_free(sc->sc_tpath, sc->sc_tpathlen); 1378 kmem_free(sc->sc_data, MAXPHYS); 1379 sc->sc_data_used = false; 1380 dk_detach(dksc); 1381 disk_detach(&dksc->sc_dkdev); 1382 1383 return 0; 1384 } 1385 1386 static int 1387 cgd_ioctl_get(dev_t dev, void *data, struct lwp *l) 1388 { 1389 struct cgd_softc *sc; 1390 struct cgd_user *cgu; 1391 int unit, error; 1392 1393 unit = CGDUNIT(dev); 1394 cgu = (struct cgd_user *)data; 1395 1396 DPRINTF_FOLLOW(("cgd_ioctl_get(0x%"PRIx64", %d, %p, %p)\n", 1397 dev, unit, data, l)); 1398 1399 /* XXX, we always return this units data, so if cgu_unit is 1400 * not -1, that field doesn't match the rest 1401 */ 1402 if (cgu->cgu_unit == -1) 1403 cgu->cgu_unit = unit; 1404 1405 if (cgu->cgu_unit < 0) 1406 return EINVAL; /* XXX: should this be ENXIO? */ 1407 1408 error = cgd_lock(false); 1409 if (error) 1410 return error; 1411 1412 sc = device_lookup_private(&cgd_cd, unit); 1413 if (sc == NULL || !DK_ATTACHED(&sc->sc_dksc)) { 1414 cgu->cgu_dev = 0; 1415 cgu->cgu_alg[0] = '\0'; 1416 cgu->cgu_blocksize = 0; 1417 cgu->cgu_mode = 0; 1418 cgu->cgu_keylen = 0; 1419 } 1420 else { 1421 mutex_enter(&sc->sc_lock); 1422 cgu->cgu_dev = sc->sc_tdev; 1423 strncpy(cgu->cgu_alg, sc->sc_cfuncs->cf_name, 1424 sizeof(cgu->cgu_alg)); 1425 cgu->cgu_blocksize = sc->sc_cdata.cf_blocksize; 1426 cgu->cgu_mode = sc->sc_cdata.cf_mode; 1427 cgu->cgu_keylen = sc->sc_cdata.cf_keylen; 1428 mutex_exit(&sc->sc_lock); 1429 } 1430 1431 cgd_unlock(); 1432 return 0; 1433 } 1434 1435 static int 1436 cgdinit(struct cgd_softc *sc, const char *cpath, struct vnode *vp, 1437 struct lwp *l) 1438 { 1439 struct disk_geom *dg; 1440 int ret; 1441 char *tmppath; 1442 uint64_t psize; 1443 unsigned secsize; 1444 struct dk_softc *dksc = &sc->sc_dksc; 1445 1446 sc->sc_tvn = vp; 1447 sc->sc_tpath = NULL; 1448 1449 tmppath = kmem_alloc(MAXPATHLEN, KM_SLEEP); 1450 ret = copyinstr(cpath, tmppath, MAXPATHLEN, &sc->sc_tpathlen); 1451 if (ret) 1452 goto bail; 1453 sc->sc_tpath = kmem_alloc(sc->sc_tpathlen, KM_SLEEP); 1454 memcpy(sc->sc_tpath, tmppath, sc->sc_tpathlen); 1455 1456 sc->sc_tdev = vp->v_rdev; 1457 1458 if ((ret = getdisksize(vp, &psize, &secsize)) != 0) 1459 goto bail; 1460 1461 if (psize == 0) { 1462 ret = ENODEV; 1463 goto bail; 1464 } 1465 1466 /* 1467 * XXX here we should probe the underlying device. If we 1468 * are accessing a partition of type RAW_PART, then 1469 * we should populate our initial geometry with the 1470 * geometry that we discover from the device. 1471 */ 1472 dg = &dksc->sc_dkdev.dk_geom; 1473 memset(dg, 0, sizeof(*dg)); 1474 dg->dg_secperunit = psize; 1475 dg->dg_secsize = secsize; 1476 dg->dg_ntracks = 1; 1477 dg->dg_nsectors = 1024 * 1024 / dg->dg_secsize; 1478 dg->dg_ncylinders = dg->dg_secperunit / dg->dg_nsectors; 1479 1480 bail: 1481 kmem_free(tmppath, MAXPATHLEN); 1482 if (ret && sc->sc_tpath) 1483 kmem_free(sc->sc_tpath, sc->sc_tpathlen); 1484 return ret; 1485 } 1486 1487 /* 1488 * Our generic cipher entry point. This takes care of the 1489 * IV mode and passes off the work to the specific cipher. 1490 * We implement here the IV method ``encrypted block 1491 * number''. 1492 * 1493 * XXXrcd: for now we rely on our own crypto framework defined 1494 * in dev/cgd_crypto.c. This will change when we 1495 * get a generic kernel crypto framework. 1496 */ 1497 1498 static void 1499 blkno2blkno_buf(char *sbuf, daddr_t blkno) 1500 { 1501 int i; 1502 1503 /* Set up the blkno in blkno_buf, here we do not care much 1504 * about the final layout of the information as long as we 1505 * can guarantee that each sector will have a different IV 1506 * and that the endianness of the machine will not affect 1507 * the representation that we have chosen. 1508 * 1509 * We choose this representation, because it does not rely 1510 * on the size of buf (which is the blocksize of the cipher), 1511 * but allows daddr_t to grow without breaking existing 1512 * disks. 1513 * 1514 * Note that blkno2blkno_buf does not take a size as input, 1515 * and hence must be called on a pre-zeroed buffer of length 1516 * greater than or equal to sizeof(daddr_t). 1517 */ 1518 for (i=0; i < sizeof(daddr_t); i++) { 1519 *sbuf++ = blkno & 0xff; 1520 blkno >>= 8; 1521 } 1522 } 1523 1524 static struct cpu_info * 1525 cgd_cpu(struct cgd_softc *sc) 1526 { 1527 struct cgd_worker *cw = sc->sc_worker; 1528 struct cpu_info *ci = NULL; 1529 u_int cidx, i; 1530 1531 if (cw->cw_busy == 0) { 1532 cw->cw_last = cpu_index(curcpu()); 1533 return NULL; 1534 } 1535 1536 for (i=0, cidx = cw->cw_last+1; i<maxcpus; ++i, ++cidx) { 1537 if (cidx >= maxcpus) 1538 cidx = 0; 1539 ci = cpu_lookup(cidx); 1540 if (ci) { 1541 cw->cw_last = cidx; 1542 break; 1543 } 1544 } 1545 1546 return ci; 1547 } 1548 1549 static void 1550 cgd_enqueue(struct cgd_softc *sc, struct cgd_xfer *cx) 1551 { 1552 struct cgd_worker *cw = sc->sc_worker; 1553 struct cpu_info *ci; 1554 1555 mutex_enter(&cw->cw_lock); 1556 ci = cgd_cpu(sc); 1557 cw->cw_busy++; 1558 mutex_exit(&cw->cw_lock); 1559 1560 workqueue_enqueue(cw->cw_wq, &cx->cx_work, ci); 1561 } 1562 1563 static void 1564 cgd_process(struct work *wk, void *arg) 1565 { 1566 struct cgd_xfer *cx = (struct cgd_xfer *)wk; 1567 struct cgd_softc *sc = cx->cx_sc; 1568 struct cgd_worker *cw = sc->sc_worker; 1569 1570 cgd_cipher(sc, cx->cx_dstv, cx->cx_srcv, cx->cx_len, 1571 cx->cx_blkno, cx->cx_secsize, cx->cx_dir); 1572 1573 if (cx->cx_dir == CGD_CIPHER_ENCRYPT) { 1574 cgd_diskstart2(sc, cx); 1575 } else { 1576 cgd_iodone2(sc, cx); 1577 } 1578 1579 mutex_enter(&cw->cw_lock); 1580 if (cw->cw_busy > 0) 1581 cw->cw_busy--; 1582 mutex_exit(&cw->cw_lock); 1583 } 1584 1585 static void 1586 cgd_cipher(struct cgd_softc *sc, void *dstv, const void *srcv, 1587 size_t len, daddr_t blkno, size_t secsize, int dir) 1588 { 1589 char *dst = dstv; 1590 const char *src = srcv; 1591 cfunc_cipher *cipher = sc->sc_cfuncs->cf_cipher; 1592 size_t blocksize = sc->sc_cdata.cf_blocksize; 1593 size_t todo; 1594 char blkno_buf[CGD_MAXBLOCKSIZE] __aligned(CGD_BLOCKALIGN); 1595 1596 DPRINTF_FOLLOW(("cgd_cipher() dir=%d\n", dir)); 1597 1598 if (sc->sc_cdata.cf_mode == CGD_CIPHER_CBC_ENCBLKNO8) 1599 blocksize /= 8; 1600 1601 KASSERT(len % blocksize == 0); 1602 /* ensure that sizeof(daddr_t) <= blocksize (for encblkno IVing) */ 1603 KASSERT(sizeof(daddr_t) <= blocksize); 1604 KASSERT(blocksize <= CGD_MAXBLOCKSIZE); 1605 1606 for (; len > 0; len -= todo) { 1607 todo = MIN(len, secsize); 1608 1609 memset(blkno_buf, 0x0, blocksize); 1610 blkno2blkno_buf(blkno_buf, blkno); 1611 IFDEBUG(CGDB_CRYPTO, hexprint("step 1: blkno_buf", 1612 blkno_buf, blocksize)); 1613 1614 /* 1615 * Handle bollocksed up encblkno8 mistake. We used to 1616 * compute the encryption of a zero block with blkno as 1617 * the CBC IV -- except in an early mistake arising 1618 * from bit/byte confusion, we actually computed the 1619 * encryption of the last of _eight_ zero blocks under 1620 * CBC as the CBC IV. 1621 * 1622 * Encrypting the block number is handled inside the 1623 * cipher dispatch now (even though in practice, both 1624 * CBC and XTS will do the same thing), so we have to 1625 * simulate the block number that would yield the same 1626 * result. So we encrypt _six_ zero blocks -- the 1627 * first one and the last one are handled inside the 1628 * cipher dispatch. 1629 */ 1630 if (sc->sc_cdata.cf_mode == CGD_CIPHER_CBC_ENCBLKNO8) { 1631 static const uint8_t zero[CGD_MAXBLOCKSIZE]; 1632 uint8_t iv[CGD_MAXBLOCKSIZE]; 1633 1634 memcpy(iv, blkno_buf, blocksize); 1635 cipher(sc->sc_cdata.cf_priv, blkno_buf, zero, 1636 6*blocksize, iv, CGD_CIPHER_ENCRYPT); 1637 memmove(blkno_buf, blkno_buf + 5*blocksize, blocksize); 1638 } 1639 1640 cipher(sc->sc_cdata.cf_priv, dst, src, todo, blkno_buf, dir); 1641 1642 dst += todo; 1643 src += todo; 1644 blkno++; 1645 } 1646 } 1647 1648 #ifdef DEBUG 1649 static void 1650 hexprint(const char *start, void *buf, int len) 1651 { 1652 char *c = buf; 1653 1654 KASSERTMSG(len >= 0, "hexprint: called with len < 0"); 1655 printf("%s: len=%06d 0x", start, len); 1656 while (len--) 1657 printf("%02x", (unsigned char) *c++); 1658 } 1659 #endif 1660 1661 static void 1662 cgd_selftest(void) 1663 { 1664 struct cgd_softc sc; 1665 void *buf; 1666 1667 for (size_t i = 0; i < __arraycount(selftests); i++) { 1668 const char *alg = selftests[i].alg; 1669 int encblkno8 = selftests[i].encblkno8; 1670 const uint8_t *key = selftests[i].key; 1671 int keylen = selftests[i].keylen; 1672 int txtlen = selftests[i].txtlen; 1673 1674 aprint_debug("cgd: self-test %s-%d%s\n", alg, keylen, 1675 encblkno8 ? " (encblkno8)" : ""); 1676 1677 memset(&sc, 0, sizeof(sc)); 1678 1679 sc.sc_cfuncs = cryptfuncs_find(alg); 1680 if (sc.sc_cfuncs == NULL) 1681 panic("%s not implemented", alg); 1682 1683 sc.sc_cdata.cf_blocksize = 8 * selftests[i].blocksize; 1684 sc.sc_cdata.cf_mode = encblkno8 ? CGD_CIPHER_CBC_ENCBLKNO8 : 1685 CGD_CIPHER_CBC_ENCBLKNO1; 1686 sc.sc_cdata.cf_keylen = keylen; 1687 1688 sc.sc_cdata.cf_priv = sc.sc_cfuncs->cf_init(keylen, 1689 key, &sc.sc_cdata.cf_blocksize); 1690 if (sc.sc_cdata.cf_priv == NULL) 1691 panic("cf_priv is NULL"); 1692 if (sc.sc_cdata.cf_blocksize > CGD_MAXBLOCKSIZE) 1693 panic("bad block size %zu", sc.sc_cdata.cf_blocksize); 1694 1695 if (!encblkno8) 1696 sc.sc_cdata.cf_blocksize /= 8; 1697 1698 buf = kmem_alloc(txtlen, KM_SLEEP); 1699 memcpy(buf, selftests[i].ptxt, txtlen); 1700 1701 cgd_cipher(&sc, buf, buf, txtlen, selftests[i].blkno, 1702 selftests[i].secsize, CGD_CIPHER_ENCRYPT); 1703 if (memcmp(buf, selftests[i].ctxt, txtlen) != 0) { 1704 hexdump(printf, "was", buf, txtlen); 1705 hexdump(printf, "exp", selftests[i].ctxt, txtlen); 1706 panic("cgd %s-%d encryption is broken [%zu]", 1707 selftests[i].alg, keylen, i); 1708 } 1709 1710 cgd_cipher(&sc, buf, buf, txtlen, selftests[i].blkno, 1711 selftests[i].secsize, CGD_CIPHER_DECRYPT); 1712 if (memcmp(buf, selftests[i].ptxt, txtlen) != 0) { 1713 hexdump(printf, "was", buf, txtlen); 1714 hexdump(printf, "exp", selftests[i].ptxt, txtlen); 1715 panic("cgd %s-%d decryption is broken [%zu]", 1716 selftests[i].alg, keylen, i); 1717 } 1718 1719 kmem_free(buf, txtlen); 1720 sc.sc_cfuncs->cf_destroy(sc.sc_cdata.cf_priv); 1721 } 1722 1723 aprint_debug("cgd: self-tests passed\n"); 1724 } 1725 1726 MODULE(MODULE_CLASS_DRIVER, cgd, "blowfish,des,dk_subr,bufq_fcfs"); 1727 1728 #ifdef _MODULE 1729 CFDRIVER_DECL(cgd, DV_DISK, NULL); 1730 1731 devmajor_t cgd_bmajor = -1, cgd_cmajor = -1; 1732 #endif 1733 1734 static int 1735 cgd_modcmd(modcmd_t cmd, void *arg) 1736 { 1737 int error = 0; 1738 1739 switch (cmd) { 1740 case MODULE_CMD_INIT: 1741 #ifdef _MODULE 1742 mutex_init(&cgd_spawning_mtx, MUTEX_DEFAULT, IPL_NONE); 1743 cv_init(&cgd_spawning_cv, "cgspwn"); 1744 1745 error = config_cfdriver_attach(&cgd_cd); 1746 if (error) 1747 break; 1748 1749 error = config_cfattach_attach(cgd_cd.cd_name, &cgd_ca); 1750 if (error) { 1751 config_cfdriver_detach(&cgd_cd); 1752 aprint_error("%s: unable to register cfattach for" 1753 "%s, error %d\n", __func__, cgd_cd.cd_name, error); 1754 break; 1755 } 1756 /* 1757 * Attach the {b,c}devsw's 1758 */ 1759 error = devsw_attach("cgd", &cgd_bdevsw, &cgd_bmajor, 1760 &cgd_cdevsw, &cgd_cmajor); 1761 1762 /* 1763 * If devsw_attach fails, remove from autoconf database 1764 */ 1765 if (error) { 1766 config_cfattach_detach(cgd_cd.cd_name, &cgd_ca); 1767 config_cfdriver_detach(&cgd_cd); 1768 aprint_error("%s: unable to attach %s devsw, " 1769 "error %d", __func__, cgd_cd.cd_name, error); 1770 break; 1771 } 1772 #endif 1773 break; 1774 1775 case MODULE_CMD_FINI: 1776 #ifdef _MODULE 1777 /* 1778 * Remove {b,c}devsw's 1779 */ 1780 devsw_detach(&cgd_bdevsw, &cgd_cdevsw); 1781 1782 /* 1783 * Now remove device from autoconf database 1784 */ 1785 error = config_cfattach_detach(cgd_cd.cd_name, &cgd_ca); 1786 if (error) { 1787 (void)devsw_attach("cgd", &cgd_bdevsw, &cgd_bmajor, 1788 &cgd_cdevsw, &cgd_cmajor); 1789 aprint_error("%s: failed to detach %s cfattach, " 1790 "error %d\n", __func__, cgd_cd.cd_name, error); 1791 break; 1792 } 1793 error = config_cfdriver_detach(&cgd_cd); 1794 if (error) { 1795 (void)config_cfattach_attach(cgd_cd.cd_name, &cgd_ca); 1796 (void)devsw_attach("cgd", &cgd_bdevsw, &cgd_bmajor, 1797 &cgd_cdevsw, &cgd_cmajor); 1798 aprint_error("%s: failed to detach %s cfdriver, " 1799 "error %d\n", __func__, cgd_cd.cd_name, error); 1800 break; 1801 } 1802 1803 cv_destroy(&cgd_spawning_cv); 1804 mutex_destroy(&cgd_spawning_mtx); 1805 #endif 1806 break; 1807 1808 case MODULE_CMD_STAT: 1809 error = ENOTTY; 1810 break; 1811 default: 1812 error = ENOTTY; 1813 break; 1814 } 1815 1816 return error; 1817 } 1818