1 /* $NetBSD: cgd.c,v 1.137 2020/06/29 23:36:06 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.137 2020/06/29 23:36:06 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 const int pmask = 1 << RAW_PART; 533 struct cgd_softc *sc = device_private(self); 534 struct dk_softc *dksc = &sc->sc_dksc; 535 536 if (DK_BUSY(dksc, pmask)) 537 return EBUSY; 538 539 if (DK_ATTACHED(dksc) && 540 (ret = cgd_ioctl_clr(sc, curlwp)) != 0) 541 return ret; 542 543 disk_destroy(&dksc->sc_dkdev); 544 cv_destroy(&sc->sc_cv); 545 mutex_destroy(&sc->sc_lock); 546 547 return 0; 548 } 549 550 void 551 cgdattach(int num) 552 { 553 #ifndef _MODULE 554 int error; 555 556 mutex_init(&cgd_spawning_mtx, MUTEX_DEFAULT, IPL_NONE); 557 cv_init(&cgd_spawning_cv, "cgspwn"); 558 559 error = config_cfattach_attach(cgd_cd.cd_name, &cgd_ca); 560 if (error != 0) 561 aprint_error("%s: unable to register cfattach\n", 562 cgd_cd.cd_name); 563 #endif 564 565 cgd_selftest(); 566 } 567 568 static struct cgd_softc * 569 cgd_spawn(int unit) 570 { 571 cfdata_t cf; 572 struct cgd_worker *cw; 573 struct cgd_softc *sc; 574 575 cf = kmem_alloc(sizeof(*cf), KM_SLEEP); 576 cf->cf_name = cgd_cd.cd_name; 577 cf->cf_atname = cgd_cd.cd_name; 578 cf->cf_unit = unit; 579 cf->cf_fstate = FSTATE_STAR; 580 581 cw = cgd_create_one_worker(); 582 if (cw == NULL) { 583 kmem_free(cf, sizeof(*cf)); 584 return NULL; 585 } 586 587 sc = device_private(config_attach_pseudo(cf)); 588 if (sc == NULL) { 589 cgd_destroy_one_worker(cw); 590 return NULL; 591 } 592 593 sc->sc_worker = cw; 594 595 return sc; 596 } 597 598 static int 599 cgd_destroy(device_t dev) 600 { 601 struct cgd_softc *sc = device_private(dev); 602 struct cgd_worker *cw = sc->sc_worker; 603 cfdata_t cf; 604 int error; 605 606 cf = device_cfdata(dev); 607 error = config_detach(dev, DETACH_QUIET); 608 if (error) 609 return error; 610 611 cgd_destroy_one_worker(cw); 612 613 kmem_free(cf, sizeof(*cf)); 614 return 0; 615 } 616 617 static void 618 cgd_busy(struct cgd_softc *sc) 619 { 620 621 mutex_enter(&sc->sc_lock); 622 while (sc->sc_busy) 623 cv_wait(&sc->sc_cv, &sc->sc_lock); 624 sc->sc_busy = true; 625 mutex_exit(&sc->sc_lock); 626 } 627 628 static void 629 cgd_unbusy(struct cgd_softc *sc) 630 { 631 632 mutex_enter(&sc->sc_lock); 633 sc->sc_busy = false; 634 cv_broadcast(&sc->sc_cv); 635 mutex_exit(&sc->sc_lock); 636 } 637 638 static struct cgd_worker * 639 cgd_create_one_worker(void) 640 { 641 KASSERT(cgd_spawning); 642 643 if (cgd_refcnt++ == 0) { 644 KASSERT(cgd_worker == NULL); 645 cgd_worker = cgd_create_worker(); 646 } 647 648 KASSERT(cgd_worker != NULL); 649 return cgd_worker; 650 } 651 652 static void 653 cgd_destroy_one_worker(struct cgd_worker *cw) 654 { 655 KASSERT(cgd_spawning); 656 KASSERT(cw == cgd_worker); 657 658 if (--cgd_refcnt == 0) { 659 cgd_destroy_worker(cgd_worker); 660 cgd_worker = NULL; 661 } 662 } 663 664 static struct cgd_worker * 665 cgd_create_worker(void) 666 { 667 struct cgd_worker *cw; 668 struct workqueue *wq; 669 struct pool *cp; 670 int error; 671 672 cw = kmem_alloc(sizeof(struct cgd_worker), KM_SLEEP); 673 cp = kmem_alloc(sizeof(struct pool), KM_SLEEP); 674 675 error = workqueue_create(&wq, "cgd", cgd_process, NULL, 676 PRI_BIO, IPL_BIO, WQ_MPSAFE | WQ_PERCPU); 677 if (error) { 678 kmem_free(cp, sizeof(struct pool)); 679 kmem_free(cw, sizeof(struct cgd_worker)); 680 return NULL; 681 } 682 683 cw->cw_cpool = cp; 684 cw->cw_wq = wq; 685 pool_init(cw->cw_cpool, sizeof(struct cgd_xfer), 0, 686 0, 0, "cgdcpl", NULL, IPL_BIO); 687 688 mutex_init(&cw->cw_lock, MUTEX_DEFAULT, IPL_BIO); 689 690 return cw; 691 } 692 693 static void 694 cgd_destroy_worker(struct cgd_worker *cw) 695 { 696 mutex_destroy(&cw->cw_lock); 697 698 if (cw->cw_cpool) { 699 pool_destroy(cw->cw_cpool); 700 kmem_free(cw->cw_cpool, sizeof(struct pool)); 701 } 702 if (cw->cw_wq) 703 workqueue_destroy(cw->cw_wq); 704 705 kmem_free(cw, sizeof(struct cgd_worker)); 706 } 707 708 static int 709 cgdopen(dev_t dev, int flags, int fmt, struct lwp *l) 710 { 711 struct cgd_softc *sc; 712 int error; 713 714 DPRINTF_FOLLOW(("cgdopen(0x%"PRIx64", %d)\n", dev, flags)); 715 716 error = cgd_lock(true); 717 if (error) 718 return error; 719 sc = getcgd_softc(dev); 720 if (sc == NULL) 721 sc = cgd_spawn(CGDUNIT(dev)); 722 cgd_unlock(); 723 if (sc == NULL) 724 return ENXIO; 725 726 return dk_open(&sc->sc_dksc, dev, flags, fmt, l); 727 } 728 729 static int 730 cgdclose(dev_t dev, int flags, int fmt, struct lwp *l) 731 { 732 struct cgd_softc *sc; 733 struct dk_softc *dksc; 734 int error; 735 736 DPRINTF_FOLLOW(("cgdclose(0x%"PRIx64", %d)\n", dev, flags)); 737 738 error = cgd_lock(false); 739 if (error) 740 return error; 741 sc = getcgd_softc(dev); 742 if (sc == NULL) { 743 error = ENXIO; 744 goto done; 745 } 746 747 dksc = &sc->sc_dksc; 748 if ((error = dk_close(dksc, dev, flags, fmt, l)) != 0) 749 goto done; 750 751 if (!DK_ATTACHED(dksc)) { 752 if ((error = cgd_destroy(sc->sc_dksc.sc_dev)) != 0) { 753 device_printf(dksc->sc_dev, 754 "unable to detach instance\n"); 755 goto done; 756 } 757 } 758 759 done: 760 cgd_unlock(); 761 762 return error; 763 } 764 765 static void 766 cgdstrategy(struct buf *bp) 767 { 768 struct cgd_softc *sc = getcgd_softc(bp->b_dev); 769 770 DPRINTF_FOLLOW(("cgdstrategy(%p): b_bcount = %ld\n", bp, 771 (long)bp->b_bcount)); 772 773 /* 774 * Reject unaligned writes. 775 */ 776 if (((uintptr_t)bp->b_data & 3) != 0) { 777 bp->b_error = EINVAL; 778 goto bail; 779 } 780 781 dk_strategy(&sc->sc_dksc, bp); 782 return; 783 784 bail: 785 bp->b_resid = bp->b_bcount; 786 biodone(bp); 787 return; 788 } 789 790 static int 791 cgdsize(dev_t dev) 792 { 793 struct cgd_softc *sc = getcgd_softc(dev); 794 795 DPRINTF_FOLLOW(("cgdsize(0x%"PRIx64")\n", dev)); 796 if (!sc) 797 return -1; 798 return dk_size(&sc->sc_dksc, dev); 799 } 800 801 /* 802 * cgd_{get,put}data are functions that deal with getting a buffer 803 * for the new encrypted data. 804 * We can no longer have a buffer per device, we need a buffer per 805 * work queue... 806 */ 807 808 static void * 809 cgd_getdata(struct cgd_softc *sc, unsigned long size) 810 { 811 void *data = NULL; 812 813 mutex_enter(&sc->sc_lock); 814 if (!sc->sc_data_used) { 815 sc->sc_data_used = true; 816 data = sc->sc_data; 817 } 818 mutex_exit(&sc->sc_lock); 819 820 if (data) 821 return data; 822 823 return kmem_intr_alloc(size, KM_NOSLEEP); 824 } 825 826 static void 827 cgd_putdata(struct cgd_softc *sc, void *data, unsigned long size) 828 { 829 830 if (data == sc->sc_data) { 831 mutex_enter(&sc->sc_lock); 832 sc->sc_data_used = false; 833 mutex_exit(&sc->sc_lock); 834 } else 835 kmem_intr_free(data, size); 836 } 837 838 static int 839 cgd_diskstart(device_t dev, struct buf *bp) 840 { 841 struct cgd_softc *sc = device_private(dev); 842 struct cgd_worker *cw = sc->sc_worker; 843 struct dk_softc *dksc = &sc->sc_dksc; 844 struct disk_geom *dg = &dksc->sc_dkdev.dk_geom; 845 struct cgd_xfer *cx; 846 struct buf *nbp; 847 void * newaddr; 848 daddr_t bn; 849 850 DPRINTF_FOLLOW(("cgd_diskstart(%p, %p)\n", dksc, bp)); 851 852 bn = bp->b_rawblkno; 853 854 /* 855 * We attempt to allocate all of our resources up front, so that 856 * we can fail quickly if they are unavailable. 857 */ 858 nbp = getiobuf(sc->sc_tvn, false); 859 if (nbp == NULL) 860 return EAGAIN; 861 862 cx = pool_get(cw->cw_cpool, PR_NOWAIT); 863 if (cx == NULL) { 864 putiobuf(nbp); 865 return EAGAIN; 866 } 867 868 cx->cx_sc = sc; 869 cx->cx_obp = bp; 870 cx->cx_nbp = nbp; 871 cx->cx_srcv = cx->cx_dstv = bp->b_data; 872 cx->cx_blkno = bn; 873 cx->cx_secsize = dg->dg_secsize; 874 875 /* 876 * If we are writing, then we need to encrypt the outgoing 877 * block into a new block of memory. 878 */ 879 if ((bp->b_flags & B_READ) == 0) { 880 newaddr = cgd_getdata(sc, bp->b_bcount); 881 if (!newaddr) { 882 pool_put(cw->cw_cpool, cx); 883 putiobuf(nbp); 884 return EAGAIN; 885 } 886 887 cx->cx_dstv = newaddr; 888 cx->cx_len = bp->b_bcount; 889 cx->cx_dir = CGD_CIPHER_ENCRYPT; 890 891 cgd_enqueue(sc, cx); 892 return 0; 893 } 894 895 cgd_diskstart2(sc, cx); 896 return 0; 897 } 898 899 static void 900 cgd_diskstart2(struct cgd_softc *sc, struct cgd_xfer *cx) 901 { 902 struct vnode *vp; 903 struct buf *bp; 904 struct buf *nbp; 905 906 bp = cx->cx_obp; 907 nbp = cx->cx_nbp; 908 909 nbp->b_data = cx->cx_dstv; 910 nbp->b_flags = bp->b_flags; 911 nbp->b_oflags = bp->b_oflags; 912 nbp->b_cflags = bp->b_cflags; 913 nbp->b_iodone = cgdiodone; 914 nbp->b_proc = bp->b_proc; 915 nbp->b_blkno = btodb(cx->cx_blkno * cx->cx_secsize); 916 nbp->b_bcount = bp->b_bcount; 917 nbp->b_private = cx; 918 919 BIO_COPYPRIO(nbp, bp); 920 921 if ((nbp->b_flags & B_READ) == 0) { 922 vp = nbp->b_vp; 923 mutex_enter(vp->v_interlock); 924 vp->v_numoutput++; 925 mutex_exit(vp->v_interlock); 926 } 927 VOP_STRATEGY(sc->sc_tvn, nbp); 928 } 929 930 static void 931 cgdiodone(struct buf *nbp) 932 { 933 struct cgd_xfer *cx = nbp->b_private; 934 struct buf *obp = cx->cx_obp; 935 struct cgd_softc *sc = getcgd_softc(obp->b_dev); 936 struct dk_softc *dksc = &sc->sc_dksc; 937 struct disk_geom *dg = &dksc->sc_dkdev.dk_geom; 938 daddr_t bn; 939 940 KDASSERT(sc); 941 942 DPRINTF_FOLLOW(("cgdiodone(%p)\n", nbp)); 943 DPRINTF(CGDB_IO, ("cgdiodone: bp %p bcount %d resid %d\n", 944 obp, obp->b_bcount, obp->b_resid)); 945 DPRINTF(CGDB_IO, (" dev 0x%"PRIx64", nbp %p bn %" PRId64 946 " addr %p bcnt %d\n", nbp->b_dev, nbp, nbp->b_blkno, nbp->b_data, 947 nbp->b_bcount)); 948 if (nbp->b_error != 0) { 949 obp->b_error = nbp->b_error; 950 DPRINTF(CGDB_IO, ("%s: error %d\n", dksc->sc_xname, 951 obp->b_error)); 952 } 953 954 /* Perform the decryption if we are reading. 955 * 956 * Note: use the blocknumber from nbp, since it is what 957 * we used to encrypt the blocks. 958 */ 959 960 if (nbp->b_flags & B_READ) { 961 bn = dbtob(nbp->b_blkno) / dg->dg_secsize; 962 963 cx->cx_obp = obp; 964 cx->cx_nbp = nbp; 965 cx->cx_dstv = obp->b_data; 966 cx->cx_srcv = obp->b_data; 967 cx->cx_len = obp->b_bcount; 968 cx->cx_blkno = bn; 969 cx->cx_secsize = dg->dg_secsize; 970 cx->cx_dir = CGD_CIPHER_DECRYPT; 971 972 cgd_enqueue(sc, cx); 973 return; 974 } 975 976 cgd_iodone2(sc, cx); 977 } 978 979 static void 980 cgd_iodone2(struct cgd_softc *sc, struct cgd_xfer *cx) 981 { 982 struct cgd_worker *cw = sc->sc_worker; 983 struct buf *obp = cx->cx_obp; 984 struct buf *nbp = cx->cx_nbp; 985 struct dk_softc *dksc = &sc->sc_dksc; 986 987 pool_put(cw->cw_cpool, cx); 988 989 /* If we allocated memory, free it now... */ 990 if (nbp->b_data != obp->b_data) 991 cgd_putdata(sc, nbp->b_data, nbp->b_bcount); 992 993 putiobuf(nbp); 994 995 /* Request is complete for whatever reason */ 996 obp->b_resid = 0; 997 if (obp->b_error != 0) 998 obp->b_resid = obp->b_bcount; 999 1000 dk_done(dksc, obp); 1001 dk_start(dksc, NULL); 1002 } 1003 1004 static int 1005 cgd_dumpblocks(device_t dev, void *va, daddr_t blkno, int nblk) 1006 { 1007 struct cgd_softc *sc = device_private(dev); 1008 struct dk_softc *dksc = &sc->sc_dksc; 1009 struct disk_geom *dg = &dksc->sc_dkdev.dk_geom; 1010 size_t nbytes, blksize; 1011 void *buf; 1012 int error; 1013 1014 /* 1015 * dk_dump gives us units of disklabel sectors. Everything 1016 * else in cgd uses units of diskgeom sectors. These had 1017 * better agree; otherwise we need to figure out how to convert 1018 * between them. 1019 */ 1020 KASSERTMSG((dg->dg_secsize == dksc->sc_dkdev.dk_label->d_secsize), 1021 "diskgeom secsize %"PRIu32" != disklabel secsize %"PRIu32, 1022 dg->dg_secsize, dksc->sc_dkdev.dk_label->d_secsize); 1023 blksize = dg->dg_secsize; 1024 1025 /* 1026 * Compute the number of bytes in this request, which dk_dump 1027 * has `helpfully' converted to a number of blocks for us. 1028 */ 1029 nbytes = nblk*blksize; 1030 1031 /* Try to acquire a buffer to store the ciphertext. */ 1032 buf = cgd_getdata(sc, nbytes); 1033 if (buf == NULL) 1034 /* Out of memory: give up. */ 1035 return ENOMEM; 1036 1037 /* Encrypt the caller's data into the temporary buffer. */ 1038 cgd_cipher(sc, buf, va, nbytes, blkno, blksize, CGD_CIPHER_ENCRYPT); 1039 1040 /* Pass it on to the underlying disk device. */ 1041 error = bdev_dump(sc->sc_tdev, blkno, buf, nbytes); 1042 1043 /* Release the buffer. */ 1044 cgd_putdata(sc, buf, nbytes); 1045 1046 /* Return any error from the underlying disk device. */ 1047 return error; 1048 } 1049 1050 /* XXX: we should probably put these into dksubr.c, mostly */ 1051 static int 1052 cgdread(dev_t dev, struct uio *uio, int flags) 1053 { 1054 struct cgd_softc *sc; 1055 struct dk_softc *dksc; 1056 1057 DPRINTF_FOLLOW(("cgdread(0x%llx, %p, %d)\n", 1058 (unsigned long long)dev, uio, flags)); 1059 sc = getcgd_softc(dev); 1060 if (sc == NULL) 1061 return ENXIO; 1062 dksc = &sc->sc_dksc; 1063 if (!DK_ATTACHED(dksc)) 1064 return ENXIO; 1065 return physio(cgdstrategy, NULL, dev, B_READ, minphys, uio); 1066 } 1067 1068 /* XXX: we should probably put these into dksubr.c, mostly */ 1069 static int 1070 cgdwrite(dev_t dev, struct uio *uio, int flags) 1071 { 1072 struct cgd_softc *sc; 1073 struct dk_softc *dksc; 1074 1075 DPRINTF_FOLLOW(("cgdwrite(0x%"PRIx64", %p, %d)\n", dev, uio, flags)); 1076 sc = getcgd_softc(dev); 1077 if (sc == NULL) 1078 return ENXIO; 1079 dksc = &sc->sc_dksc; 1080 if (!DK_ATTACHED(dksc)) 1081 return ENXIO; 1082 return physio(cgdstrategy, NULL, dev, B_WRITE, minphys, uio); 1083 } 1084 1085 static int 1086 cgdioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l) 1087 { 1088 struct cgd_softc *sc; 1089 struct dk_softc *dksc; 1090 int part = DISKPART(dev); 1091 int pmask = 1 << part; 1092 int error; 1093 1094 DPRINTF_FOLLOW(("cgdioctl(0x%"PRIx64", %ld, %p, %d, %p)\n", 1095 dev, cmd, data, flag, l)); 1096 1097 switch (cmd) { 1098 case CGDIOCGET: 1099 return cgd_ioctl_get(dev, data, l); 1100 case CGDIOCSET: 1101 case CGDIOCCLR: 1102 if ((flag & FWRITE) == 0) 1103 return EBADF; 1104 /* FALLTHROUGH */ 1105 default: 1106 sc = getcgd_softc(dev); 1107 if (sc == NULL) 1108 return ENXIO; 1109 dksc = &sc->sc_dksc; 1110 break; 1111 } 1112 1113 switch (cmd) { 1114 case CGDIOCSET: 1115 cgd_busy(sc); 1116 if (DK_ATTACHED(dksc)) 1117 error = EBUSY; 1118 else 1119 error = cgd_ioctl_set(sc, data, l); 1120 cgd_unbusy(sc); 1121 break; 1122 case CGDIOCCLR: 1123 cgd_busy(sc); 1124 if (DK_BUSY(&sc->sc_dksc, pmask)) 1125 error = EBUSY; 1126 else 1127 error = cgd_ioctl_clr(sc, l); 1128 cgd_unbusy(sc); 1129 break; 1130 case DIOCGCACHE: 1131 case DIOCCACHESYNC: 1132 cgd_busy(sc); 1133 if (!DK_ATTACHED(dksc)) { 1134 cgd_unbusy(sc); 1135 error = ENOENT; 1136 break; 1137 } 1138 /* 1139 * We pass this call down to the underlying disk. 1140 */ 1141 error = VOP_IOCTL(sc->sc_tvn, cmd, data, flag, l->l_cred); 1142 cgd_unbusy(sc); 1143 break; 1144 case DIOCGSECTORALIGN: { 1145 struct disk_sectoralign *dsa = data; 1146 1147 cgd_busy(sc); 1148 if (!DK_ATTACHED(dksc)) { 1149 cgd_unbusy(sc); 1150 error = ENOENT; 1151 break; 1152 } 1153 1154 /* Get the underlying disk's sector alignment. */ 1155 error = VOP_IOCTL(sc->sc_tvn, cmd, data, flag, l->l_cred); 1156 if (error) { 1157 cgd_unbusy(sc); 1158 break; 1159 } 1160 1161 /* Adjust for the disklabel partition if necessary. */ 1162 if (part != RAW_PART) { 1163 struct disklabel *lp = dksc->sc_dkdev.dk_label; 1164 daddr_t offset = lp->d_partitions[part].p_offset; 1165 uint32_t r = offset % dsa->dsa_alignment; 1166 1167 if (r < dsa->dsa_firstaligned) 1168 dsa->dsa_firstaligned = dsa->dsa_firstaligned 1169 - r; 1170 else 1171 dsa->dsa_firstaligned = (dsa->dsa_firstaligned 1172 + dsa->dsa_alignment) - r; 1173 } 1174 cgd_unbusy(sc); 1175 break; 1176 } 1177 case DIOCGSTRATEGY: 1178 case DIOCSSTRATEGY: 1179 if (!DK_ATTACHED(dksc)) { 1180 error = ENOENT; 1181 break; 1182 } 1183 /*FALLTHROUGH*/ 1184 default: 1185 error = dk_ioctl(dksc, dev, cmd, data, flag, l); 1186 break; 1187 case CGDIOCGET: 1188 KASSERT(0); 1189 error = EINVAL; 1190 } 1191 1192 return error; 1193 } 1194 1195 static int 1196 cgddump(dev_t dev, daddr_t blkno, void *va, size_t size) 1197 { 1198 struct cgd_softc *sc; 1199 1200 DPRINTF_FOLLOW(("cgddump(0x%"PRIx64", %" PRId64 ", %p, %lu)\n", 1201 dev, blkno, va, (unsigned long)size)); 1202 sc = getcgd_softc(dev); 1203 if (sc == NULL) 1204 return ENXIO; 1205 return dk_dump(&sc->sc_dksc, dev, blkno, va, size, DK_DUMP_RECURSIVE); 1206 } 1207 1208 /* 1209 * XXXrcd: 1210 * for now we hardcode the maximum key length. 1211 */ 1212 #define MAX_KEYSIZE 1024 1213 1214 static const struct { 1215 const char *n; 1216 int v; 1217 int d; 1218 } encblkno[] = { 1219 { "encblkno", CGD_CIPHER_CBC_ENCBLKNO8, 1 }, 1220 { "encblkno8", CGD_CIPHER_CBC_ENCBLKNO8, 1 }, 1221 { "encblkno1", CGD_CIPHER_CBC_ENCBLKNO1, 8 }, 1222 }; 1223 1224 /* ARGSUSED */ 1225 static int 1226 cgd_ioctl_set(struct cgd_softc *sc, void *data, struct lwp *l) 1227 { 1228 struct cgd_ioctl *ci = data; 1229 struct vnode *vp; 1230 int ret; 1231 size_t i; 1232 size_t keybytes; /* key length in bytes */ 1233 const char *cp; 1234 struct pathbuf *pb; 1235 char *inbuf; 1236 struct dk_softc *dksc = &sc->sc_dksc; 1237 1238 cp = ci->ci_disk; 1239 1240 ret = pathbuf_copyin(ci->ci_disk, &pb); 1241 if (ret != 0) { 1242 return ret; 1243 } 1244 ret = vn_bdev_openpath(pb, &vp, l); 1245 pathbuf_destroy(pb); 1246 if (ret != 0) { 1247 return ret; 1248 } 1249 1250 inbuf = kmem_alloc(MAX_KEYSIZE, KM_SLEEP); 1251 1252 if ((ret = cgdinit(sc, cp, vp, l)) != 0) 1253 goto bail; 1254 1255 (void)memset(inbuf, 0, MAX_KEYSIZE); 1256 ret = copyinstr(ci->ci_alg, inbuf, 256, NULL); 1257 if (ret) 1258 goto bail; 1259 sc->sc_cfuncs = cryptfuncs_find(inbuf); 1260 if (!sc->sc_cfuncs) { 1261 ret = EINVAL; 1262 goto bail; 1263 } 1264 1265 (void)memset(inbuf, 0, MAX_KEYSIZE); 1266 ret = copyinstr(ci->ci_ivmethod, inbuf, MAX_KEYSIZE, NULL); 1267 if (ret) 1268 goto bail; 1269 1270 for (i = 0; i < __arraycount(encblkno); i++) 1271 if (strcmp(encblkno[i].n, inbuf) == 0) 1272 break; 1273 1274 if (i == __arraycount(encblkno)) { 1275 ret = EINVAL; 1276 goto bail; 1277 } 1278 1279 keybytes = ci->ci_keylen / 8 + 1; 1280 if (keybytes > MAX_KEYSIZE) { 1281 ret = EINVAL; 1282 goto bail; 1283 } 1284 1285 (void)memset(inbuf, 0, MAX_KEYSIZE); 1286 ret = copyin(ci->ci_key, inbuf, keybytes); 1287 if (ret) 1288 goto bail; 1289 1290 sc->sc_cdata.cf_blocksize = ci->ci_blocksize; 1291 sc->sc_cdata.cf_mode = encblkno[i].v; 1292 1293 /* 1294 * Print a warning if the user selected the legacy encblkno8 1295 * mistake, and reject it altogether for ciphers that it 1296 * doesn't apply to. 1297 */ 1298 if (encblkno[i].v != CGD_CIPHER_CBC_ENCBLKNO1) { 1299 if (strcmp(sc->sc_cfuncs->cf_name, "aes-cbc") && 1300 strcmp(sc->sc_cfuncs->cf_name, "3des-cbc") && 1301 strcmp(sc->sc_cfuncs->cf_name, "blowfish-cbc")) { 1302 log(LOG_WARNING, "cgd: %s only makes sense for cbc," 1303 " not for %s; ignoring\n", 1304 encblkno[i].n, sc->sc_cfuncs->cf_name); 1305 sc->sc_cdata.cf_mode = CGD_CIPHER_CBC_ENCBLKNO1; 1306 } else { 1307 log(LOG_WARNING, "cgd: enabling legacy encblkno8\n"); 1308 } 1309 } 1310 1311 sc->sc_cdata.cf_keylen = ci->ci_keylen; 1312 sc->sc_cdata.cf_priv = sc->sc_cfuncs->cf_init(ci->ci_keylen, inbuf, 1313 &sc->sc_cdata.cf_blocksize); 1314 if (sc->sc_cdata.cf_blocksize > CGD_MAXBLOCKSIZE) { 1315 log(LOG_WARNING, "cgd: Disallowed cipher with blocksize %zu > %u\n", 1316 sc->sc_cdata.cf_blocksize, CGD_MAXBLOCKSIZE); 1317 sc->sc_cdata.cf_priv = NULL; 1318 } 1319 1320 /* 1321 * The blocksize is supposed to be in bytes. Unfortunately originally 1322 * it was expressed in bits. For compatibility we maintain encblkno 1323 * and encblkno8. 1324 */ 1325 sc->sc_cdata.cf_blocksize /= encblkno[i].d; 1326 (void)explicit_memset(inbuf, 0, MAX_KEYSIZE); 1327 if (!sc->sc_cdata.cf_priv) { 1328 ret = EINVAL; /* XXX is this the right error? */ 1329 goto bail; 1330 } 1331 kmem_free(inbuf, MAX_KEYSIZE); 1332 1333 bufq_alloc(&dksc->sc_bufq, "fcfs", 0); 1334 1335 sc->sc_data = kmem_alloc(MAXPHYS, KM_SLEEP); 1336 sc->sc_data_used = false; 1337 1338 /* Attach the disk. */ 1339 dk_attach(dksc); 1340 disk_attach(&dksc->sc_dkdev); 1341 1342 disk_set_info(dksc->sc_dev, &dksc->sc_dkdev, NULL); 1343 1344 /* Discover wedges on this disk. */ 1345 dkwedge_discover(&dksc->sc_dkdev); 1346 1347 return 0; 1348 1349 bail: 1350 kmem_free(inbuf, MAX_KEYSIZE); 1351 (void)vn_close(vp, FREAD|FWRITE, l->l_cred); 1352 return ret; 1353 } 1354 1355 /* ARGSUSED */ 1356 static int 1357 cgd_ioctl_clr(struct cgd_softc *sc, struct lwp *l) 1358 { 1359 struct dk_softc *dksc = &sc->sc_dksc; 1360 1361 if (!DK_ATTACHED(dksc)) 1362 return ENXIO; 1363 1364 /* Delete all of our wedges. */ 1365 dkwedge_delall(&dksc->sc_dkdev); 1366 1367 /* Kill off any queued buffers. */ 1368 dk_drain(dksc); 1369 bufq_free(dksc->sc_bufq); 1370 1371 (void)vn_close(sc->sc_tvn, FREAD|FWRITE, l->l_cred); 1372 sc->sc_cfuncs->cf_destroy(sc->sc_cdata.cf_priv); 1373 kmem_free(sc->sc_tpath, sc->sc_tpathlen); 1374 kmem_free(sc->sc_data, MAXPHYS); 1375 sc->sc_data_used = false; 1376 dk_detach(dksc); 1377 disk_detach(&dksc->sc_dkdev); 1378 1379 return 0; 1380 } 1381 1382 static int 1383 cgd_ioctl_get(dev_t dev, void *data, struct lwp *l) 1384 { 1385 struct cgd_softc *sc; 1386 struct cgd_user *cgu; 1387 int unit, error; 1388 1389 unit = CGDUNIT(dev); 1390 cgu = (struct cgd_user *)data; 1391 1392 DPRINTF_FOLLOW(("cgd_ioctl_get(0x%"PRIx64", %d, %p, %p)\n", 1393 dev, unit, data, l)); 1394 1395 /* XXX, we always return this units data, so if cgu_unit is 1396 * not -1, that field doesn't match the rest 1397 */ 1398 if (cgu->cgu_unit == -1) 1399 cgu->cgu_unit = unit; 1400 1401 if (cgu->cgu_unit < 0) 1402 return EINVAL; /* XXX: should this be ENXIO? */ 1403 1404 error = cgd_lock(false); 1405 if (error) 1406 return error; 1407 1408 sc = device_lookup_private(&cgd_cd, unit); 1409 if (sc == NULL || !DK_ATTACHED(&sc->sc_dksc)) { 1410 cgu->cgu_dev = 0; 1411 cgu->cgu_alg[0] = '\0'; 1412 cgu->cgu_blocksize = 0; 1413 cgu->cgu_mode = 0; 1414 cgu->cgu_keylen = 0; 1415 } 1416 else { 1417 mutex_enter(&sc->sc_lock); 1418 cgu->cgu_dev = sc->sc_tdev; 1419 strncpy(cgu->cgu_alg, sc->sc_cfuncs->cf_name, 1420 sizeof(cgu->cgu_alg)); 1421 cgu->cgu_blocksize = sc->sc_cdata.cf_blocksize; 1422 cgu->cgu_mode = sc->sc_cdata.cf_mode; 1423 cgu->cgu_keylen = sc->sc_cdata.cf_keylen; 1424 mutex_exit(&sc->sc_lock); 1425 } 1426 1427 cgd_unlock(); 1428 return 0; 1429 } 1430 1431 static int 1432 cgdinit(struct cgd_softc *sc, const char *cpath, struct vnode *vp, 1433 struct lwp *l) 1434 { 1435 struct disk_geom *dg; 1436 int ret; 1437 char *tmppath; 1438 uint64_t psize; 1439 unsigned secsize; 1440 struct dk_softc *dksc = &sc->sc_dksc; 1441 1442 sc->sc_tvn = vp; 1443 sc->sc_tpath = NULL; 1444 1445 tmppath = kmem_alloc(MAXPATHLEN, KM_SLEEP); 1446 ret = copyinstr(cpath, tmppath, MAXPATHLEN, &sc->sc_tpathlen); 1447 if (ret) 1448 goto bail; 1449 sc->sc_tpath = kmem_alloc(sc->sc_tpathlen, KM_SLEEP); 1450 memcpy(sc->sc_tpath, tmppath, sc->sc_tpathlen); 1451 1452 sc->sc_tdev = vp->v_rdev; 1453 1454 if ((ret = getdisksize(vp, &psize, &secsize)) != 0) 1455 goto bail; 1456 1457 if (psize == 0) { 1458 ret = ENODEV; 1459 goto bail; 1460 } 1461 1462 /* 1463 * XXX here we should probe the underlying device. If we 1464 * are accessing a partition of type RAW_PART, then 1465 * we should populate our initial geometry with the 1466 * geometry that we discover from the device. 1467 */ 1468 dg = &dksc->sc_dkdev.dk_geom; 1469 memset(dg, 0, sizeof(*dg)); 1470 dg->dg_secperunit = psize; 1471 dg->dg_secsize = secsize; 1472 dg->dg_ntracks = 1; 1473 dg->dg_nsectors = 1024 * 1024 / dg->dg_secsize; 1474 dg->dg_ncylinders = dg->dg_secperunit / dg->dg_nsectors; 1475 1476 bail: 1477 kmem_free(tmppath, MAXPATHLEN); 1478 if (ret && sc->sc_tpath) 1479 kmem_free(sc->sc_tpath, sc->sc_tpathlen); 1480 return ret; 1481 } 1482 1483 /* 1484 * Our generic cipher entry point. This takes care of the 1485 * IV mode and passes off the work to the specific cipher. 1486 * We implement here the IV method ``encrypted block 1487 * number''. 1488 * 1489 * XXXrcd: for now we rely on our own crypto framework defined 1490 * in dev/cgd_crypto.c. This will change when we 1491 * get a generic kernel crypto framework. 1492 */ 1493 1494 static void 1495 blkno2blkno_buf(char *sbuf, daddr_t blkno) 1496 { 1497 int i; 1498 1499 /* Set up the blkno in blkno_buf, here we do not care much 1500 * about the final layout of the information as long as we 1501 * can guarantee that each sector will have a different IV 1502 * and that the endianness of the machine will not affect 1503 * the representation that we have chosen. 1504 * 1505 * We choose this representation, because it does not rely 1506 * on the size of buf (which is the blocksize of the cipher), 1507 * but allows daddr_t to grow without breaking existing 1508 * disks. 1509 * 1510 * Note that blkno2blkno_buf does not take a size as input, 1511 * and hence must be called on a pre-zeroed buffer of length 1512 * greater than or equal to sizeof(daddr_t). 1513 */ 1514 for (i=0; i < sizeof(daddr_t); i++) { 1515 *sbuf++ = blkno & 0xff; 1516 blkno >>= 8; 1517 } 1518 } 1519 1520 static struct cpu_info * 1521 cgd_cpu(struct cgd_softc *sc) 1522 { 1523 struct cgd_worker *cw = sc->sc_worker; 1524 struct cpu_info *ci = NULL; 1525 u_int cidx, i; 1526 1527 if (cw->cw_busy == 0) { 1528 cw->cw_last = cpu_index(curcpu()); 1529 return NULL; 1530 } 1531 1532 for (i=0, cidx = cw->cw_last+1; i<maxcpus; ++i, ++cidx) { 1533 if (cidx >= maxcpus) 1534 cidx = 0; 1535 ci = cpu_lookup(cidx); 1536 if (ci) { 1537 cw->cw_last = cidx; 1538 break; 1539 } 1540 } 1541 1542 return ci; 1543 } 1544 1545 static void 1546 cgd_enqueue(struct cgd_softc *sc, struct cgd_xfer *cx) 1547 { 1548 struct cgd_worker *cw = sc->sc_worker; 1549 struct cpu_info *ci; 1550 1551 mutex_enter(&cw->cw_lock); 1552 ci = cgd_cpu(sc); 1553 cw->cw_busy++; 1554 mutex_exit(&cw->cw_lock); 1555 1556 workqueue_enqueue(cw->cw_wq, &cx->cx_work, ci); 1557 } 1558 1559 static void 1560 cgd_process(struct work *wk, void *arg) 1561 { 1562 struct cgd_xfer *cx = (struct cgd_xfer *)wk; 1563 struct cgd_softc *sc = cx->cx_sc; 1564 struct cgd_worker *cw = sc->sc_worker; 1565 1566 cgd_cipher(sc, cx->cx_dstv, cx->cx_srcv, cx->cx_len, 1567 cx->cx_blkno, cx->cx_secsize, cx->cx_dir); 1568 1569 if (cx->cx_dir == CGD_CIPHER_ENCRYPT) { 1570 cgd_diskstart2(sc, cx); 1571 } else { 1572 cgd_iodone2(sc, cx); 1573 } 1574 1575 mutex_enter(&cw->cw_lock); 1576 if (cw->cw_busy > 0) 1577 cw->cw_busy--; 1578 mutex_exit(&cw->cw_lock); 1579 } 1580 1581 static void 1582 cgd_cipher(struct cgd_softc *sc, void *dstv, const void *srcv, 1583 size_t len, daddr_t blkno, size_t secsize, int dir) 1584 { 1585 char *dst = dstv; 1586 const char *src = srcv; 1587 cfunc_cipher *cipher = sc->sc_cfuncs->cf_cipher; 1588 size_t blocksize = sc->sc_cdata.cf_blocksize; 1589 size_t todo; 1590 char blkno_buf[CGD_MAXBLOCKSIZE] __aligned(CGD_BLOCKALIGN); 1591 1592 DPRINTF_FOLLOW(("cgd_cipher() dir=%d\n", dir)); 1593 1594 if (sc->sc_cdata.cf_mode == CGD_CIPHER_CBC_ENCBLKNO8) 1595 blocksize /= 8; 1596 1597 KASSERT(len % blocksize == 0); 1598 /* ensure that sizeof(daddr_t) <= blocksize (for encblkno IVing) */ 1599 KASSERT(sizeof(daddr_t) <= blocksize); 1600 KASSERT(blocksize <= CGD_MAXBLOCKSIZE); 1601 1602 for (; len > 0; len -= todo) { 1603 todo = MIN(len, secsize); 1604 1605 memset(blkno_buf, 0x0, blocksize); 1606 blkno2blkno_buf(blkno_buf, blkno); 1607 IFDEBUG(CGDB_CRYPTO, hexprint("step 1: blkno_buf", 1608 blkno_buf, blocksize)); 1609 1610 /* 1611 * Handle bollocksed up encblkno8 mistake. We used to 1612 * compute the encryption of a zero block with blkno as 1613 * the CBC IV -- except in an early mistake arising 1614 * from bit/byte confusion, we actually computed the 1615 * encryption of the last of _eight_ zero blocks under 1616 * CBC as the CBC IV. 1617 * 1618 * Encrypting the block number is handled inside the 1619 * cipher dispatch now (even though in practice, both 1620 * CBC and XTS will do the same thing), so we have to 1621 * simulate the block number that would yield the same 1622 * result. So we encrypt _six_ zero blocks -- the 1623 * first one and the last one are handled inside the 1624 * cipher dispatch. 1625 */ 1626 if (sc->sc_cdata.cf_mode == CGD_CIPHER_CBC_ENCBLKNO8) { 1627 static const uint8_t zero[CGD_MAXBLOCKSIZE]; 1628 uint8_t iv[CGD_MAXBLOCKSIZE]; 1629 1630 memcpy(iv, blkno_buf, blocksize); 1631 cipher(sc->sc_cdata.cf_priv, blkno_buf, zero, 1632 6*blocksize, iv, CGD_CIPHER_ENCRYPT); 1633 memmove(blkno_buf, blkno_buf + 5*blocksize, blocksize); 1634 } 1635 1636 cipher(sc->sc_cdata.cf_priv, dst, src, todo, blkno_buf, dir); 1637 1638 dst += todo; 1639 src += todo; 1640 blkno++; 1641 } 1642 } 1643 1644 #ifdef DEBUG 1645 static void 1646 hexprint(const char *start, void *buf, int len) 1647 { 1648 char *c = buf; 1649 1650 KASSERTMSG(len >= 0, "hexprint: called with len < 0"); 1651 printf("%s: len=%06d 0x", start, len); 1652 while (len--) 1653 printf("%02x", (unsigned char) *c++); 1654 } 1655 #endif 1656 1657 static void 1658 cgd_selftest(void) 1659 { 1660 struct cgd_softc sc; 1661 void *buf; 1662 1663 for (size_t i = 0; i < __arraycount(selftests); i++) { 1664 const char *alg = selftests[i].alg; 1665 int encblkno8 = selftests[i].encblkno8; 1666 const uint8_t *key = selftests[i].key; 1667 int keylen = selftests[i].keylen; 1668 int txtlen = selftests[i].txtlen; 1669 1670 aprint_verbose("cgd: self-test %s-%d%s\n", alg, keylen, 1671 encblkno8 ? " (encblkno8)" : ""); 1672 1673 memset(&sc, 0, sizeof(sc)); 1674 1675 sc.sc_cfuncs = cryptfuncs_find(alg); 1676 if (sc.sc_cfuncs == NULL) 1677 panic("%s not implemented", alg); 1678 1679 sc.sc_cdata.cf_blocksize = 8 * selftests[i].blocksize; 1680 sc.sc_cdata.cf_mode = encblkno8 ? CGD_CIPHER_CBC_ENCBLKNO8 : 1681 CGD_CIPHER_CBC_ENCBLKNO1; 1682 sc.sc_cdata.cf_keylen = keylen; 1683 1684 sc.sc_cdata.cf_priv = sc.sc_cfuncs->cf_init(keylen, 1685 key, &sc.sc_cdata.cf_blocksize); 1686 if (sc.sc_cdata.cf_priv == NULL) 1687 panic("cf_priv is NULL"); 1688 if (sc.sc_cdata.cf_blocksize > CGD_MAXBLOCKSIZE) 1689 panic("bad block size %zu", sc.sc_cdata.cf_blocksize); 1690 1691 if (!encblkno8) 1692 sc.sc_cdata.cf_blocksize /= 8; 1693 1694 buf = kmem_alloc(txtlen, KM_SLEEP); 1695 memcpy(buf, selftests[i].ptxt, txtlen); 1696 1697 cgd_cipher(&sc, buf, buf, txtlen, selftests[i].blkno, 1698 selftests[i].secsize, CGD_CIPHER_ENCRYPT); 1699 if (memcmp(buf, selftests[i].ctxt, txtlen) != 0) { 1700 hexdump(printf, "was", buf, txtlen); 1701 hexdump(printf, "exp", selftests[i].ctxt, txtlen); 1702 panic("cgd %s-%d encryption is broken [%zu]", 1703 selftests[i].alg, keylen, i); 1704 } 1705 1706 cgd_cipher(&sc, buf, buf, txtlen, selftests[i].blkno, 1707 selftests[i].secsize, CGD_CIPHER_DECRYPT); 1708 if (memcmp(buf, selftests[i].ptxt, txtlen) != 0) { 1709 hexdump(printf, "was", buf, txtlen); 1710 hexdump(printf, "exp", selftests[i].ptxt, txtlen); 1711 panic("cgd %s-%d decryption is broken [%zu]", 1712 selftests[i].alg, keylen, i); 1713 } 1714 1715 kmem_free(buf, txtlen); 1716 sc.sc_cfuncs->cf_destroy(sc.sc_cdata.cf_priv); 1717 } 1718 1719 aprint_verbose("cgd: self-tests passed\n"); 1720 } 1721 1722 MODULE(MODULE_CLASS_DRIVER, cgd, "blowfish,des,dk_subr,bufq_fcfs"); 1723 1724 #ifdef _MODULE 1725 CFDRIVER_DECL(cgd, DV_DISK, NULL); 1726 1727 devmajor_t cgd_bmajor = -1, cgd_cmajor = -1; 1728 #endif 1729 1730 static int 1731 cgd_modcmd(modcmd_t cmd, void *arg) 1732 { 1733 int error = 0; 1734 1735 switch (cmd) { 1736 case MODULE_CMD_INIT: 1737 #ifdef _MODULE 1738 mutex_init(&cgd_spawning_mtx, MUTEX_DEFAULT, IPL_NONE); 1739 cv_init(&cgd_spawning_cv, "cgspwn"); 1740 1741 error = config_cfdriver_attach(&cgd_cd); 1742 if (error) 1743 break; 1744 1745 error = config_cfattach_attach(cgd_cd.cd_name, &cgd_ca); 1746 if (error) { 1747 config_cfdriver_detach(&cgd_cd); 1748 aprint_error("%s: unable to register cfattach for" 1749 "%s, error %d\n", __func__, cgd_cd.cd_name, error); 1750 break; 1751 } 1752 /* 1753 * Attach the {b,c}devsw's 1754 */ 1755 error = devsw_attach("cgd", &cgd_bdevsw, &cgd_bmajor, 1756 &cgd_cdevsw, &cgd_cmajor); 1757 1758 /* 1759 * If devsw_attach fails, remove from autoconf database 1760 */ 1761 if (error) { 1762 config_cfattach_detach(cgd_cd.cd_name, &cgd_ca); 1763 config_cfdriver_detach(&cgd_cd); 1764 aprint_error("%s: unable to attach %s devsw, " 1765 "error %d", __func__, cgd_cd.cd_name, error); 1766 break; 1767 } 1768 #endif 1769 break; 1770 1771 case MODULE_CMD_FINI: 1772 #ifdef _MODULE 1773 /* 1774 * Remove {b,c}devsw's 1775 */ 1776 devsw_detach(&cgd_bdevsw, &cgd_cdevsw); 1777 1778 /* 1779 * Now remove device from autoconf database 1780 */ 1781 error = config_cfattach_detach(cgd_cd.cd_name, &cgd_ca); 1782 if (error) { 1783 (void)devsw_attach("cgd", &cgd_bdevsw, &cgd_bmajor, 1784 &cgd_cdevsw, &cgd_cmajor); 1785 aprint_error("%s: failed to detach %s cfattach, " 1786 "error %d\n", __func__, cgd_cd.cd_name, error); 1787 break; 1788 } 1789 error = config_cfdriver_detach(&cgd_cd); 1790 if (error) { 1791 (void)config_cfattach_attach(cgd_cd.cd_name, &cgd_ca); 1792 (void)devsw_attach("cgd", &cgd_bdevsw, &cgd_bmajor, 1793 &cgd_cdevsw, &cgd_cmajor); 1794 aprint_error("%s: failed to detach %s cfdriver, " 1795 "error %d\n", __func__, cgd_cd.cd_name, error); 1796 break; 1797 } 1798 1799 cv_destroy(&cgd_spawning_cv); 1800 mutex_destroy(&cgd_spawning_mtx); 1801 #endif 1802 break; 1803 1804 case MODULE_CMD_STAT: 1805 error = ENOTTY; 1806 break; 1807 default: 1808 error = ENOTTY; 1809 break; 1810 } 1811 1812 return error; 1813 } 1814