1 1.17 joerg /* $NetBSD: fwcrom.c,v 1.17 2014/11/21 23:37:25 joerg Exp $ */ 2 1.1 kiyohara /*- 3 1.1 kiyohara * Copyright (c) 2002-2003 4 1.1 kiyohara * Hidetoshi Shimokawa. All rights reserved. 5 1.11 kiyohara * 6 1.1 kiyohara * Redistribution and use in source and binary forms, with or without 7 1.1 kiyohara * modification, are permitted provided that the following conditions 8 1.1 kiyohara * are met: 9 1.1 kiyohara * 1. Redistributions of source code must retain the above copyright 10 1.1 kiyohara * notice, this list of conditions and the following disclaimer. 11 1.1 kiyohara * 2. Redistributions in binary form must reproduce the above copyright 12 1.1 kiyohara * notice, this list of conditions and the following disclaimer in the 13 1.1 kiyohara * documentation and/or other materials provided with the distribution. 14 1.1 kiyohara * 3. All advertising materials mentioning features or use of this software 15 1.1 kiyohara * must display the following acknowledgement: 16 1.1 kiyohara * 17 1.1 kiyohara * This product includes software developed by Hidetoshi Shimokawa. 18 1.1 kiyohara * 19 1.1 kiyohara * 4. Neither the name of the author nor the names of its contributors 20 1.1 kiyohara * may be used to endorse or promote products derived from this software 21 1.1 kiyohara * without specific prior written permission. 22 1.11 kiyohara * 23 1.1 kiyohara * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24 1.1 kiyohara * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 1.1 kiyohara * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 1.1 kiyohara * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27 1.1 kiyohara * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 1.1 kiyohara * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 1.1 kiyohara * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 1.1 kiyohara * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 1.1 kiyohara * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 1.1 kiyohara * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 1.1 kiyohara * SUCH DAMAGE. 34 1.1 kiyohara */ 35 1.1 kiyohara 36 1.6 lukem #include <sys/cdefs.h> 37 1.17 joerg __KERNEL_RCSID(0, "$NetBSD: fwcrom.c,v 1.17 2014/11/21 23:37:25 joerg Exp $"); 38 1.1 kiyohara 39 1.1 kiyohara #include <sys/param.h> 40 1.1 kiyohara #ifdef _KERNEL 41 1.1 kiyohara #include <sys/device.h> 42 1.1 kiyohara #include <sys/errno.h> 43 1.1 kiyohara #include <sys/systm.h> 44 1.1 kiyohara #else 45 1.1 kiyohara #include <stdio.h> 46 1.1 kiyohara #include <string.h> 47 1.1 kiyohara #endif 48 1.1 kiyohara #include <dev/ieee1394/firewire.h> 49 1.1 kiyohara #include <dev/ieee1394/iec13213.h> 50 1.1 kiyohara 51 1.16 christos #define MAX_ROM (1024 - sizeof(uint32_t) * 5) 52 1.4 christos #define CROM_END(cc) ((char *)(cc)->stack[0].dir + MAX_ROM - 1) 53 1.1 kiyohara 54 1.1 kiyohara void 55 1.16 christos crom_init_context(struct crom_context *cc, uint32_t *p) 56 1.1 kiyohara { 57 1.1 kiyohara struct csrhdr *hdr; 58 1.1 kiyohara 59 1.1 kiyohara hdr = (struct csrhdr *)p; 60 1.1 kiyohara if (hdr->info_len <= 1) { 61 1.1 kiyohara /* minimum or invalid ROM */ 62 1.1 kiyohara cc->depth = -1; 63 1.1 kiyohara return; 64 1.1 kiyohara } 65 1.1 kiyohara p += 1 + hdr->info_len; 66 1.1 kiyohara 67 1.1 kiyohara /* check size of root directory */ 68 1.1 kiyohara if (((struct csrdirectory *)p)->crc_len == 0) { 69 1.1 kiyohara cc->depth = -1; 70 1.1 kiyohara return; 71 1.1 kiyohara } 72 1.1 kiyohara cc->depth = 0; 73 1.1 kiyohara cc->stack[0].dir = (struct csrdirectory *)p; 74 1.1 kiyohara cc->stack[0].index = 0; 75 1.1 kiyohara } 76 1.1 kiyohara 77 1.1 kiyohara struct csrreg * 78 1.1 kiyohara crom_get(struct crom_context *cc) 79 1.1 kiyohara { 80 1.1 kiyohara struct crom_ptr *ptr; 81 1.1 kiyohara 82 1.1 kiyohara ptr = &cc->stack[cc->depth]; 83 1.11 kiyohara return &ptr->dir->entry[ptr->index]; 84 1.1 kiyohara } 85 1.1 kiyohara 86 1.1 kiyohara void 87 1.1 kiyohara crom_next(struct crom_context *cc) 88 1.1 kiyohara { 89 1.1 kiyohara struct crom_ptr *ptr; 90 1.1 kiyohara struct csrreg *reg; 91 1.1 kiyohara 92 1.1 kiyohara if (cc->depth < 0) 93 1.1 kiyohara return; 94 1.1 kiyohara reg = crom_get(cc); 95 1.1 kiyohara if ((reg->key & CSRTYPE_MASK) == CSRTYPE_D) { 96 1.1 kiyohara if (cc->depth >= CROM_MAX_DEPTH) { 97 1.1 kiyohara printf("crom_next: too deep\n"); 98 1.1 kiyohara goto again; 99 1.1 kiyohara } 100 1.11 kiyohara cc->depth++; 101 1.1 kiyohara 102 1.1 kiyohara ptr = &cc->stack[cc->depth]; 103 1.11 kiyohara ptr->dir = (struct csrdirectory *)(reg + reg->val); 104 1.1 kiyohara ptr->index = 0; 105 1.1 kiyohara goto check; 106 1.1 kiyohara } 107 1.1 kiyohara again: 108 1.1 kiyohara ptr = &cc->stack[cc->depth]; 109 1.11 kiyohara ptr->index++; 110 1.1 kiyohara check: 111 1.1 kiyohara if (ptr->index < ptr->dir->crc_len && 112 1.11 kiyohara (char *)crom_get(cc) <= CROM_END(cc)) 113 1.1 kiyohara return; 114 1.1 kiyohara 115 1.1 kiyohara if (ptr->index < ptr->dir->crc_len) 116 1.1 kiyohara printf("crom_next: bound check failed\n"); 117 1.1 kiyohara 118 1.1 kiyohara if (cc->depth > 0) { 119 1.1 kiyohara cc->depth--; 120 1.1 kiyohara goto again; 121 1.1 kiyohara } 122 1.1 kiyohara /* no more data */ 123 1.1 kiyohara cc->depth = -1; 124 1.1 kiyohara } 125 1.1 kiyohara 126 1.1 kiyohara 127 1.1 kiyohara struct csrreg * 128 1.1 kiyohara crom_search_key(struct crom_context *cc, uint8_t key) 129 1.1 kiyohara { 130 1.1 kiyohara struct csrreg *reg; 131 1.1 kiyohara 132 1.11 kiyohara while (cc->depth >= 0) { 133 1.1 kiyohara reg = crom_get(cc); 134 1.1 kiyohara if (reg->key == key) 135 1.1 kiyohara return reg; 136 1.1 kiyohara crom_next(cc); 137 1.1 kiyohara } 138 1.1 kiyohara return NULL; 139 1.1 kiyohara } 140 1.1 kiyohara 141 1.1 kiyohara int 142 1.16 christos crom_has_specver(uint32_t *p, uint32_t spec, uint32_t ver) 143 1.1 kiyohara { 144 1.1 kiyohara struct csrreg *reg; 145 1.1 kiyohara struct crom_context c, *cc; 146 1.1 kiyohara int state = 0; 147 1.1 kiyohara 148 1.1 kiyohara cc = &c; 149 1.1 kiyohara crom_init_context(cc, p); 150 1.11 kiyohara while (cc->depth >= 0) { 151 1.1 kiyohara reg = crom_get(cc); 152 1.1 kiyohara if (state == 0) { 153 1.1 kiyohara if (reg->key == CSRKEY_SPEC && reg->val == spec) 154 1.1 kiyohara state = 1; 155 1.1 kiyohara else 156 1.1 kiyohara state = 0; 157 1.1 kiyohara } else { 158 1.1 kiyohara if (reg->key == CSRKEY_VER && reg->val == ver) 159 1.1 kiyohara return 1; 160 1.1 kiyohara else 161 1.1 kiyohara state = 0; 162 1.1 kiyohara } 163 1.1 kiyohara crom_next(cc); 164 1.1 kiyohara } 165 1.1 kiyohara return 0; 166 1.1 kiyohara } 167 1.1 kiyohara 168 1.1 kiyohara void 169 1.1 kiyohara crom_parse_text(struct crom_context *cc, char *buf, int len) 170 1.1 kiyohara { 171 1.1 kiyohara struct csrreg *reg; 172 1.1 kiyohara struct csrtext *textleaf; 173 1.16 christos uint32_t *bp; 174 1.1 kiyohara int i, qlen; 175 1.17 joerg static const char nullstr[] = "(null)"; 176 1.1 kiyohara 177 1.1 kiyohara if (cc->depth < 0) 178 1.1 kiyohara return; 179 1.1 kiyohara 180 1.1 kiyohara reg = crom_get(cc); 181 1.13 cegger switch (reg->key) { 182 1.13 cegger case CROM_TEXTLEAF: 183 1.13 cegger case CROM_TEXTLEAF2: 184 1.13 cegger break; 185 1.13 cegger default: 186 1.13 cegger if ((char *)(reg + reg->val) > CROM_END(cc)) { 187 1.13 cegger strncpy(buf, nullstr, len); 188 1.13 cegger return; 189 1.13 cegger } 190 1.13 cegger break; 191 1.1 kiyohara } 192 1.1 kiyohara textleaf = (struct csrtext *)(reg + reg->val); 193 1.1 kiyohara 194 1.4 christos if ((char *)textleaf + textleaf->crc_len > CROM_END(cc)) { 195 1.1 kiyohara strncpy(buf, nullstr, len); 196 1.1 kiyohara return; 197 1.1 kiyohara } 198 1.1 kiyohara 199 1.1 kiyohara /* XXX should check spec and type */ 200 1.1 kiyohara 201 1.16 christos bp = (uint32_t *)buf; 202 1.1 kiyohara qlen = textleaf->crc_len - 2; 203 1.1 kiyohara if (len < qlen * 4) 204 1.1 kiyohara qlen = len/4; 205 1.11 kiyohara for (i = 0; i < qlen; i++) 206 1.1 kiyohara *bp++ = ntohl(textleaf->text[i]); 207 1.1 kiyohara /* make sure to terminate the string */ 208 1.1 kiyohara if (len <= qlen * 4) 209 1.1 kiyohara buf[len - 1] = 0; 210 1.1 kiyohara else 211 1.1 kiyohara buf[qlen * 4] = 0; 212 1.1 kiyohara } 213 1.1 kiyohara 214 1.1 kiyohara uint16_t 215 1.16 christos crom_crc(uint32_t *ptr, int len) 216 1.1 kiyohara { 217 1.1 kiyohara int i, shift; 218 1.16 christos uint32_t data, sum, crc = 0; 219 1.1 kiyohara 220 1.1 kiyohara for (i = 0; i < len; i++) { 221 1.1 kiyohara data = ptr[i]; 222 1.1 kiyohara for (shift = 28; shift >= 0; shift -= 4) { 223 1.1 kiyohara sum = ((crc >> 12) ^ (data >> shift)) & 0xf; 224 1.1 kiyohara crc = (crc << 4) ^ (sum << 12) ^ (sum << 5) ^ sum; 225 1.1 kiyohara } 226 1.1 kiyohara crc &= 0xffff; 227 1.1 kiyohara } 228 1.11 kiyohara return (uint16_t)crc; 229 1.1 kiyohara } 230 1.1 kiyohara 231 1.5 kiyohara #if !defined(_KERNEL) && !defined(_BOOT) 232 1.1 kiyohara static void 233 1.16 christos crom_desc_specver(uint32_t spec, uint32_t ver, char *buf, int len) 234 1.1 kiyohara { 235 1.7 xtraeme const char *s = NULL; 236 1.1 kiyohara 237 1.1 kiyohara if (spec == CSRVAL_ANSIT10 || spec == 0) { 238 1.1 kiyohara switch (ver) { 239 1.1 kiyohara case CSRVAL_T10SBP2: 240 1.1 kiyohara s = "SBP-2"; 241 1.1 kiyohara break; 242 1.1 kiyohara default: 243 1.1 kiyohara if (spec != 0) 244 1.1 kiyohara s = "unknown ANSIT10"; 245 1.1 kiyohara } 246 1.1 kiyohara } 247 1.1 kiyohara if (spec == CSRVAL_1394TA || spec == 0) { 248 1.1 kiyohara switch (ver) { 249 1.1 kiyohara case CSR_PROTAVC: 250 1.1 kiyohara s = "AV/C"; 251 1.1 kiyohara break; 252 1.1 kiyohara case CSR_PROTCAL: 253 1.1 kiyohara s = "CAL"; 254 1.1 kiyohara break; 255 1.1 kiyohara case CSR_PROTEHS: 256 1.1 kiyohara s = "EHS"; 257 1.1 kiyohara break; 258 1.1 kiyohara case CSR_PROTHAVI: 259 1.1 kiyohara s = "HAVi"; 260 1.1 kiyohara break; 261 1.1 kiyohara case CSR_PROTCAM104: 262 1.1 kiyohara s = "1394 Cam 1.04"; 263 1.1 kiyohara break; 264 1.1 kiyohara case CSR_PROTCAM120: 265 1.1 kiyohara s = "1394 Cam 1.20"; 266 1.1 kiyohara break; 267 1.1 kiyohara case CSR_PROTCAM130: 268 1.1 kiyohara s = "1394 Cam 1.30"; 269 1.1 kiyohara break; 270 1.1 kiyohara case CSR_PROTDPP: 271 1.1 kiyohara s = "1394 Direct print"; 272 1.1 kiyohara break; 273 1.1 kiyohara case CSR_PROTIICP: 274 1.1 kiyohara s = "Industrial & Instrument"; 275 1.1 kiyohara break; 276 1.1 kiyohara default: 277 1.1 kiyohara if (spec != 0) 278 1.1 kiyohara s = "unknown 1394TA"; 279 1.1 kiyohara } 280 1.1 kiyohara } 281 1.1 kiyohara if (s != NULL) 282 1.1 kiyohara snprintf(buf, len, "%s", s); 283 1.1 kiyohara } 284 1.1 kiyohara 285 1.7 xtraeme const char * 286 1.14 christos crom_desc(struct crom_context *cc, char *buf, size_t len) 287 1.1 kiyohara { 288 1.1 kiyohara struct csrreg *reg; 289 1.1 kiyohara struct csrdirectory *dir; 290 1.7 xtraeme const char *desc; 291 1.1 kiyohara uint16_t crc; 292 1.14 christos size_t l = 0; 293 1.1 kiyohara 294 1.1 kiyohara reg = crom_get(cc); 295 1.1 kiyohara switch (reg->key & CSRTYPE_MASK) { 296 1.1 kiyohara case CSRTYPE_I: 297 1.1 kiyohara #if 0 298 1.14 christos l += snprintf(buf + l, len - l, "0x%x", reg->val); 299 1.1 kiyohara #else 300 1.1 kiyohara *buf = '\0'; 301 1.1 kiyohara #endif 302 1.1 kiyohara break; 303 1.1 kiyohara case CSRTYPE_C: 304 1.14 christos l += snprintf(buf + l, len - l, "offset=0x%04x(%d)", 305 1.14 christos reg->val, reg->val); 306 1.1 kiyohara break; 307 1.1 kiyohara case CSRTYPE_L: 308 1.1 kiyohara /* XXX fall through */ 309 1.1 kiyohara case CSRTYPE_D: 310 1.1 kiyohara dir = (struct csrdirectory *) (reg + reg->val); 311 1.16 christos crc = crom_crc((uint32_t *)dir->entry, dir->crc_len); 312 1.14 christos l += snprintf(buf + l, len - l, "len=%d crc=0x%04x ", 313 1.13 cegger dir->crc_len, crc); 314 1.13 cegger 315 1.14 christos if (l > len) 316 1.14 christos l = len; 317 1.13 cegger if (crc == dir->crc) 318 1.14 christos l += snprintf(buf + l, len - l, "(OK) "); 319 1.13 cegger else 320 1.14 christos l += snprintf(buf + l, len - l, "(NG, 0x%x) ", 321 1.13 cegger dir->crc); 322 1.1 kiyohara } 323 1.14 christos if (l > len) 324 1.14 christos l = len; 325 1.1 kiyohara switch (reg->key) { 326 1.13 cegger case CSRKEY_VENDOR: /* 0x03 */ 327 1.1 kiyohara desc = "module_vendor_ID"; 328 1.1 kiyohara break; 329 1.13 cegger case CSRKEY_HW: /* 0x04 */ 330 1.1 kiyohara desc = "hardware_version"; 331 1.1 kiyohara break; 332 1.13 cegger case CSRKEY_NCAP: /* 0x0c */ 333 1.1 kiyohara desc = "node_capabilities"; 334 1.1 kiyohara break; 335 1.13 cegger case CSRKEY_SPEC: /* 0x12 */ 336 1.1 kiyohara desc = "unit_spec_ID"; 337 1.1 kiyohara break; 338 1.13 cegger case CSRKEY_VER: /* 0x13 */ 339 1.1 kiyohara desc = "unit_sw_version"; 340 1.1 kiyohara crom_desc_specver(0, reg->val, buf, len); 341 1.1 kiyohara break; 342 1.13 cegger case CSRKEY_DINFO: /* 0x14 */ 343 1.1 kiyohara desc = "logical_unit_number"; 344 1.1 kiyohara break; 345 1.13 cegger case CSRKEY_MODEL: /* 0x17 */ 346 1.1 kiyohara desc = "model_ID"; 347 1.1 kiyohara break; 348 1.13 cegger case CSRKEY_REV: /* 0x21 */ 349 1.13 cegger desc = "revision_ID"; 350 1.13 cegger break; 351 1.1 kiyohara case 0x38: 352 1.1 kiyohara desc = "command_set_spec_ID"; 353 1.1 kiyohara break; 354 1.1 kiyohara case 0x39: 355 1.1 kiyohara desc = "command_set"; 356 1.1 kiyohara break; 357 1.1 kiyohara case 0x3a: 358 1.1 kiyohara desc = "unit_characteristics"; 359 1.1 kiyohara break; 360 1.1 kiyohara case 0x3b: 361 1.1 kiyohara desc = "command_set_revision"; 362 1.1 kiyohara break; 363 1.1 kiyohara case 0x3c: 364 1.1 kiyohara desc = "firmware_revision"; 365 1.1 kiyohara break; 366 1.1 kiyohara case 0x3d: 367 1.1 kiyohara desc = "reconnect_timeout"; 368 1.1 kiyohara break; 369 1.13 cegger case 0x40: 370 1.13 cegger desc = "command_regs_base"; 371 1.13 cegger break; 372 1.1 kiyohara case 0x54: 373 1.1 kiyohara desc = "management_agent"; 374 1.1 kiyohara break; 375 1.13 cegger case CROM_TEXTLEAF: /* 0x81 */ 376 1.13 cegger case CROM_TEXTLEAF2: /* 0x82 */ 377 1.1 kiyohara desc = "text_leaf"; 378 1.14 christos crom_parse_text(cc, buf + l, len - l); 379 1.1 kiyohara break; 380 1.13 cegger case CROM_NODEID: /* 0x8d */ 381 1.13 cegger desc = "node_unique_ID"; 382 1.13 cegger break; 383 1.1 kiyohara case 0xd1: 384 1.1 kiyohara desc = "unit_directory"; 385 1.1 kiyohara break; 386 1.1 kiyohara case 0xd4: 387 1.1 kiyohara desc = "logical_unit_directory"; 388 1.1 kiyohara break; 389 1.1 kiyohara default: 390 1.1 kiyohara desc = "unknown"; 391 1.1 kiyohara } 392 1.1 kiyohara return desc; 393 1.1 kiyohara } 394 1.1 kiyohara #endif 395 1.1 kiyohara 396 1.5 kiyohara #if defined(_KERNEL) || defined(_BOOT) || defined(TEST) 397 1.1 kiyohara 398 1.1 kiyohara int 399 1.16 christos crom_add_quad(struct crom_chunk *chunk, uint32_t entry) 400 1.1 kiyohara { 401 1.1 kiyohara int index; 402 1.1 kiyohara 403 1.1 kiyohara index = chunk->data.crc_len; 404 1.1 kiyohara if (index >= CROM_MAX_CHUNK_LEN - 1) { 405 1.1 kiyohara printf("too large chunk %d\n", index); 406 1.11 kiyohara return -1; 407 1.1 kiyohara } 408 1.1 kiyohara chunk->data.buf[index] = entry; 409 1.1 kiyohara chunk->data.crc_len++; 410 1.11 kiyohara return index; 411 1.1 kiyohara } 412 1.1 kiyohara 413 1.1 kiyohara int 414 1.1 kiyohara crom_add_entry(struct crom_chunk *chunk, int key, int val) 415 1.1 kiyohara { 416 1.3 skrll union { 417 1.3 skrll struct csrreg reg; 418 1.16 christos uint32_t i; 419 1.5 kiyohara } foo; 420 1.11 kiyohara 421 1.5 kiyohara foo.reg.key = key; 422 1.5 kiyohara foo.reg.val = val; 423 1.3 skrll 424 1.11 kiyohara return crom_add_quad(chunk, foo.i); 425 1.1 kiyohara } 426 1.1 kiyohara 427 1.1 kiyohara int 428 1.1 kiyohara crom_add_chunk(struct crom_src *src, struct crom_chunk *parent, 429 1.11 kiyohara struct crom_chunk *child, int key) 430 1.1 kiyohara { 431 1.1 kiyohara int index; 432 1.1 kiyohara 433 1.1 kiyohara if (parent == NULL) { 434 1.1 kiyohara STAILQ_INSERT_TAIL(&src->chunk_list, child, link); 435 1.11 kiyohara return 0; 436 1.1 kiyohara } 437 1.1 kiyohara 438 1.1 kiyohara index = crom_add_entry(parent, key, 0); 439 1.11 kiyohara if (index < 0) 440 1.11 kiyohara return -1; 441 1.1 kiyohara child->ref_chunk = parent; 442 1.1 kiyohara child->ref_index = index; 443 1.1 kiyohara STAILQ_INSERT_TAIL(&src->chunk_list, child, link); 444 1.11 kiyohara return index; 445 1.1 kiyohara } 446 1.1 kiyohara 447 1.1 kiyohara #define MAX_TEXT (int)((CROM_MAX_CHUNK_LEN + 1) * 4 - sizeof(struct csrtext)) 448 1.1 kiyohara int 449 1.1 kiyohara crom_add_simple_text(struct crom_src *src, struct crom_chunk *parent, 450 1.11 kiyohara struct crom_chunk *chunk, const char *buf) 451 1.1 kiyohara { 452 1.1 kiyohara struct csrtext *tl; 453 1.16 christos uint32_t *p; 454 1.1 kiyohara int len, i; 455 1.1 kiyohara char t[MAX_TEXT]; 456 1.1 kiyohara 457 1.1 kiyohara len = strlen(buf); 458 1.1 kiyohara if (len > MAX_TEXT) { 459 1.1 kiyohara printf("text(%d) trancated to %d.\n", len, MAX_TEXT); 460 1.1 kiyohara len = MAX_TEXT; 461 1.1 kiyohara } 462 1.1 kiyohara 463 1.1 kiyohara tl = (struct csrtext *) &chunk->data; 464 1.16 christos tl->crc_len = howmany(sizeof(struct csrtext) + len, sizeof(uint32_t)); 465 1.1 kiyohara tl->spec_id = 0; 466 1.1 kiyohara tl->spec_type = 0; 467 1.1 kiyohara tl->lang_id = 0; 468 1.16 christos memset(t, 0, roundup2(len, sizeof(uint32_t))); 469 1.11 kiyohara memcpy(t, buf, len); 470 1.16 christos p = (uint32_t *)t; 471 1.16 christos for (i = 0; i < howmany(len, sizeof(uint32_t)); i++) 472 1.1 kiyohara tl->text[i] = ntohl(*p++); 473 1.11 kiyohara return crom_add_chunk(src, parent, chunk, CROM_TEXTLEAF); 474 1.1 kiyohara } 475 1.1 kiyohara 476 1.1 kiyohara static int 477 1.16 christos crom_copy(uint32_t *src, uint32_t *dst, int *offset, int len, int maxlen) 478 1.1 kiyohara { 479 1.11 kiyohara 480 1.1 kiyohara if (*offset + len > maxlen) { 481 1.1 kiyohara printf("Config. ROM is too large for the buffer\n"); 482 1.11 kiyohara return -1; 483 1.1 kiyohara } 484 1.16 christos memcpy((char *)(dst + *offset), src, len * sizeof(uint32_t)); 485 1.1 kiyohara *offset += len; 486 1.11 kiyohara return 0; 487 1.1 kiyohara } 488 1.1 kiyohara 489 1.1 kiyohara int 490 1.16 christos crom_load(struct crom_src *src, uint32_t *buf, int maxlen) 491 1.1 kiyohara { 492 1.1 kiyohara struct crom_chunk *chunk, *parent; 493 1.1 kiyohara struct csrhdr *hdr; 494 1.5 kiyohara #if defined(_KERNEL) || defined(_BOOT) 495 1.16 christos uint32_t *ptr; 496 1.1 kiyohara int i; 497 1.1 kiyohara #endif 498 1.1 kiyohara int count, offset; 499 1.1 kiyohara int len; 500 1.1 kiyohara 501 1.1 kiyohara offset = 0; 502 1.1 kiyohara /* Determine offset */ 503 1.1 kiyohara STAILQ_FOREACH(chunk, &src->chunk_list, link) { 504 1.1 kiyohara chunk->offset = offset; 505 1.1 kiyohara /* Assume the offset of the parent is already known */ 506 1.1 kiyohara parent = chunk->ref_chunk; 507 1.1 kiyohara if (parent != NULL) { 508 1.1 kiyohara struct csrreg *reg; 509 1.11 kiyohara const int ref_index = chunk->ref_index; 510 1.11 kiyohara 511 1.11 kiyohara reg = (struct csrreg *)&parent->data.buf[ref_index]; 512 1.11 kiyohara reg->val = 513 1.11 kiyohara offset - (parent->offset + 1 + chunk->ref_index); 514 1.1 kiyohara } 515 1.11 kiyohara offset += (1 + chunk->data.crc_len); 516 1.1 kiyohara } 517 1.1 kiyohara 518 1.1 kiyohara /* Calculate CRC and dump to the buffer */ 519 1.1 kiyohara len = 1 + src->hdr.info_len; 520 1.1 kiyohara count = 0; 521 1.16 christos if (crom_copy((uint32_t *)&src->hdr, buf, &count, len, maxlen) < 0) 522 1.11 kiyohara return -1; 523 1.1 kiyohara STAILQ_FOREACH(chunk, &src->chunk_list, link) { 524 1.1 kiyohara chunk->data.crc = 525 1.11 kiyohara crom_crc(chunk->data.buf, chunk->data.crc_len); 526 1.1 kiyohara 527 1.1 kiyohara len = 1 + chunk->data.crc_len; 528 1.16 christos if (crom_copy((uint32_t *)&chunk->data, buf, &count, len, 529 1.11 kiyohara maxlen) < 0) 530 1.11 kiyohara return -1; 531 1.1 kiyohara } 532 1.1 kiyohara hdr = (struct csrhdr *)buf; 533 1.1 kiyohara hdr->crc_len = count - 1; 534 1.1 kiyohara hdr->crc = crom_crc(&buf[1], hdr->crc_len); 535 1.1 kiyohara 536 1.5 kiyohara #if defined(_KERNEL) || defined(_BOOT) 537 1.1 kiyohara /* byte swap */ 538 1.1 kiyohara ptr = buf; 539 1.11 kiyohara for (i = 0; i < count; i++) { 540 1.1 kiyohara *ptr = htonl(*ptr); 541 1.1 kiyohara ptr++; 542 1.1 kiyohara } 543 1.1 kiyohara #endif 544 1.1 kiyohara 545 1.11 kiyohara return count; 546 1.1 kiyohara } 547 1.1 kiyohara #endif 548 1.1 kiyohara 549 1.1 kiyohara #ifdef TEST 550 1.1 kiyohara int 551 1.12 cegger main(void) 552 1.12 cegger { 553 1.1 kiyohara struct crom_src src; 554 1.15 christos struct crom_chunk root, unit[3], text[7]; 555 1.16 christos uint32_t buf[256], *p; 556 1.1 kiyohara int i; 557 1.11 kiyohara extern const char ostype[]; 558 1.1 kiyohara 559 1.8 cegger memset(&src, 0, sizeof(src)); 560 1.8 cegger memset(&root, 0, sizeof(root)); 561 1.15 christos memset(unit, 0, sizeof(unit)); 562 1.15 christos memset(text, 0, sizeof(text)); 563 1.8 cegger memset(buf, 0, sizeof(buf)); 564 1.1 kiyohara 565 1.1 kiyohara /* BUS info sample */ 566 1.1 kiyohara src.hdr.info_len = 4; 567 1.1 kiyohara src.businfo.bus_name = CSR_BUS_NAME_IEEE1394; 568 1.1 kiyohara src.businfo.eui64.hi = 0x11223344; 569 1.1 kiyohara src.businfo.eui64.lo = 0x55667788; 570 1.1 kiyohara src.businfo.link_spd = FWSPD_S400; 571 1.1 kiyohara src.businfo.generation = 0; 572 1.1 kiyohara src.businfo.max_rom = MAXROM_4; 573 1.1 kiyohara src.businfo.max_rec = 10; 574 1.1 kiyohara src.businfo.cyc_clk_acc = 100; 575 1.1 kiyohara src.businfo.pmc = 0; 576 1.1 kiyohara src.businfo.bmc = 1; 577 1.1 kiyohara src.businfo.isc = 1; 578 1.1 kiyohara src.businfo.cmc = 1; 579 1.1 kiyohara src.businfo.irmc = 1; 580 1.1 kiyohara STAILQ_INIT(&src.chunk_list); 581 1.1 kiyohara 582 1.1 kiyohara /* Root directory */ 583 1.1 kiyohara crom_add_chunk(&src, NULL, &root, 0); 584 1.1 kiyohara crom_add_entry(&root, CSRKEY_NCAP, 0x123456); 585 1.1 kiyohara /* private company_id */ 586 1.1 kiyohara crom_add_entry(&root, CSRKEY_VENDOR, 0xacde48); 587 1.1 kiyohara 588 1.15 christos crom_add_simple_text(&src, &root, &text[0], ostype); 589 1.11 kiyohara crom_add_entry(&root, CSRKEY_HW, __NetBSD_Version__); 590 1.15 christos crom_add_simple_text(&src, &root, &text[1], OS_VER_STR); 591 1.1 kiyohara 592 1.1 kiyohara /* SBP unit directory */ 593 1.15 christos crom_add_chunk(&src, &root, &unit[0], CROM_UDIR); 594 1.15 christos crom_add_entry(&unit[0], CSRKEY_SPEC, CSRVAL_ANSIT10); 595 1.15 christos crom_add_entry(&unit[0], CSRKEY_VER, CSRVAL_T10SBP2); 596 1.15 christos crom_add_entry(&unit[0], CSRKEY_COM_SPEC, CSRVAL_ANSIT10); 597 1.15 christos crom_add_entry(&unit[0], CSRKEY_COM_SET, CSRVAL_SCSI); 598 1.1 kiyohara /* management_agent */ 599 1.15 christos crom_add_entry(&unit[0], CROM_MGM, 0x1000); 600 1.15 christos crom_add_entry(&unit[0], CSRKEY_UNIT_CH, (10<<8) | 8); 601 1.1 kiyohara /* Device type and LUN */ 602 1.15 christos crom_add_entry(&unit[0], CROM_LUN, 0); 603 1.15 christos crom_add_entry(&unit[0], CSRKEY_MODEL, 1); 604 1.15 christos crom_add_simple_text(&src, &unit[0], &text[2], "scsi_target"); 605 1.1 kiyohara 606 1.1 kiyohara /* RFC2734 IPv4 over IEEE1394 */ 607 1.15 christos crom_add_chunk(&src, &root, &unit[1], CROM_UDIR); 608 1.15 christos crom_add_entry(&unit[1], CSRKEY_SPEC, CSRVAL_IETF); 609 1.15 christos crom_add_simple_text(&src, &unit[1], &text[3], "IANA"); 610 1.15 christos crom_add_entry(&unit[1], CSRKEY_VER, 1); 611 1.15 christos crom_add_simple_text(&src, &unit[1], &text[4], "IPv4"); 612 1.1 kiyohara 613 1.1 kiyohara /* RFC3146 IPv6 over IEEE1394 */ 614 1.15 christos crom_add_chunk(&src, &root, &unit[2], CROM_UDIR); 615 1.15 christos crom_add_entry(&unit[2], CSRKEY_SPEC, CSRVAL_IETF); 616 1.15 christos crom_add_simple_text(&src, &unit[2], &text[5], "IANA"); 617 1.15 christos crom_add_entry(&unit[2], CSRKEY_VER, 2); 618 1.15 christos crom_add_simple_text(&src, &unit[2], &text[6], "IPv6"); 619 1.1 kiyohara 620 1.1 kiyohara crom_load(&src, buf, 256); 621 1.1 kiyohara p = buf; 622 1.11 kiyohara #define DUMP_FORMAT "%08x %08x %08x %08x %08x %08x %08x %08x\n" 623 1.11 kiyohara for (i = 0; i < 256 / 8; i++) { 624 1.1 kiyohara printf(DUMP_FORMAT, 625 1.11 kiyohara p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]); 626 1.1 kiyohara p += 8; 627 1.1 kiyohara } 628 1.11 kiyohara return 0; 629 1.1 kiyohara } 630 1.1 kiyohara #endif 631