Home | History | Annotate | Line # | Download | only in std
ieee1212.c revision 1.10.74.2
      1  1.10.74.2      yamt /*	$NetBSD: ieee1212.c,v 1.10.74.2 2009/05/16 10:41:45 yamt Exp $	*/
      2        1.1       jmc 
      3        1.1       jmc /*
      4        1.1       jmc  * Copyright (c) 2000 The NetBSD Foundation, Inc.
      5        1.1       jmc  * All rights reserved.
      6        1.1       jmc  *
      7        1.1       jmc  * This code is derived from software contributed to The NetBSD Foundation
      8        1.1       jmc  * by James Chacon.
      9        1.1       jmc  *
     10        1.1       jmc  * Redistribution and use in source and binary forms, with or without
     11        1.1       jmc  * modification, are permitted provided that the following conditions
     12        1.1       jmc  * are met:
     13        1.1       jmc  * 1. Redistributions of source code must retain the above copyright
     14        1.1       jmc  *    notice, this list of conditions and the following disclaimer.
     15        1.1       jmc  * 2. Redistributions in binary form must reproduce the above copyright
     16        1.1       jmc  *    notice, this list of conditions and the following disclaimer in the
     17        1.1       jmc  *    documentation and/or other materials provided with the distribution.
     18        1.1       jmc  *
     19        1.1       jmc  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20        1.1       jmc  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21        1.1       jmc  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22        1.1       jmc  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23        1.1       jmc  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24        1.1       jmc  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25        1.1       jmc  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26        1.1       jmc  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27        1.1       jmc  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28        1.1       jmc  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29        1.1       jmc  * POSSIBILITY OF SUCH DAMAGE.
     30        1.1       jmc  */
     31        1.6     lukem 
     32        1.6     lukem #include <sys/cdefs.h>
     33  1.10.74.2      yamt __KERNEL_RCSID(0, "$NetBSD: ieee1212.c,v 1.10.74.2 2009/05/16 10:41:45 yamt Exp $");
     34        1.1       jmc 
     35        1.1       jmc #include <sys/param.h>
     36        1.1       jmc #include <sys/systm.h>
     37        1.1       jmc #include <sys/device.h>
     38        1.1       jmc #include <sys/kernel.h>
     39        1.1       jmc #include <sys/malloc.h>
     40        1.1       jmc 
     41        1.1       jmc #include <dev/std/ieee1212reg.h>
     42        1.1       jmc #include <dev/std/ieee1212var.h>
     43        1.1       jmc 
     44        1.1       jmc static const char * const p1212_keytype_strings[] = P1212_KEYTYPE_STRINGS ;
     45        1.9     perry static const char * const p1212_keyvalue_strings[] = P1212_KEYVALUE_STRINGS ;
     46        1.1       jmc 
     47        1.1       jmc static u_int16_t p1212_calc_crc(u_int32_t, u_int32_t *, int, int);
     48        1.1       jmc static int p1212_parse_directory(struct p1212_dir *, u_int32_t *, u_int32_t);
     49        1.1       jmc static struct p1212_leafdata *p1212_parse_leaf(u_int32_t *);
     50        1.1       jmc static int p1212_parse_textdir(struct p1212_com *, u_int32_t *);
     51        1.1       jmc static struct p1212_textdata *p1212_parse_text_desc(u_int32_t *);
     52        1.1       jmc static void p1212_print_node(struct p1212_key *, void *);
     53        1.1       jmc static int p1212_validate_offset(u_int16_t, u_int32_t);
     54        1.1       jmc static int p1212_validate_immed(u_int16_t, u_int32_t);
     55        1.1       jmc static int p1212_validate_leaf(u_int16_t, u_int32_t);
     56        1.1       jmc static int p1212_validate_dir(u_int16_t, u_int32_t);
     57        1.1       jmc 
     58        1.1       jmc #ifdef P1212_DEBUG
     59        1.1       jmc #define DPRINTF(x)      if (p1212debug) printf x
     60        1.1       jmc #define DPRINTFN(n,x)   if (p1212debug>(n)) printf x
     61        1.1       jmc int     p1212debug = 1;
     62        1.1       jmc #else
     63        1.1       jmc #define DPRINTF(x)
     64        1.1       jmc #define DPRINTFN(n,x)
     65        1.1       jmc #endif
     66        1.1       jmc 
     67        1.1       jmc /*
     68        1.1       jmc  * Routines to parse the ROM into a tree that's usable. Also verify integrity
     69        1.1       jmc  * vs. the P1212 standard
     70        1.1       jmc  */
     71        1.1       jmc 
     72        1.1       jmc /*
     73        1.1       jmc  * A buffer of u_int32_t's and a size in quads gets passed in. The output will
     74        1.1       jmc  * return -1 on error, or 0 on success and possibly reset *size to a larger
     75        1.1       jmc  * value.
     76        1.1       jmc  *
     77        1.5       wiz  * NOTE: Rom's are guaranteed per the ISO spec to be contiguous but only the
     78        1.1       jmc  * first 1k is directly mapped. Anything past 1k is supposed to use a loop
     79        1.1       jmc  * around the indirect registers to read in the rom. This code only assumes the
     80        1.1       jmc  * buffer passed in represents a total rom regardless of end size. It is the
     81        1.1       jmc  * callers responsibility to treat a size > 1024 as a special case.
     82        1.1       jmc  */
     83        1.1       jmc 
     84        1.1       jmc int
     85        1.1       jmc p1212_iscomplete(u_int32_t *t, u_int32_t *size)
     86        1.1       jmc {
     87        1.9     perry 	u_int16_t infolen, crclen, len;
     88        1.1       jmc 	u_int32_t newlen, offset, test;
     89        1.1       jmc 	int complete, i, numdirs, type, val, *dirs;
     90        1.1       jmc 
     91        1.1       jmc 	dirs = NULL;
     92        1.1       jmc 
     93        1.1       jmc 	if (*size == 0) {
     94        1.1       jmc 		DPRINTF(("Invalid size for ROM: %d\n", (unsigned int)*size));
     95        1.1       jmc 		return -1;
     96        1.1       jmc 	}
     97        1.1       jmc 
     98        1.1       jmc 	infolen = P1212_ROMFMT_GET_INFOLEN((ntohl(t[0])));
     99        1.1       jmc 	if (infolen <= 1) {
    100        1.1       jmc 		DPRINTF(("ROM not initialized or minimal ROM: Info "
    101        1.1       jmc 		    "length: %d\n", infolen));
    102        1.1       jmc 		return -1;
    103        1.1       jmc 	}
    104        1.1       jmc 	crclen = P1212_ROMFMT_GET_CRCLEN((ntohl(t[0])));
    105        1.1       jmc 	if (crclen < infolen) {
    106        1.1       jmc 		DPRINTF(("CRC len less than info len. CRC len: %d, "
    107        1.1       jmc 		    "Info len: %d\n", crclen, infolen));
    108        1.1       jmc 		return -1;
    109        1.1       jmc 	}
    110        1.9     perry 
    111        1.1       jmc 	/*
    112        1.1       jmc 	 * Now loop through it to check if all the offsets referenced are
    113        1.1       jmc 	 * within the image stored so far. If not, get those as well.
    114        1.1       jmc 	 */
    115        1.9     perry 
    116        1.1       jmc 	offset = P1212_ROMFMT_GET_INFOLEN((ntohl(t[0]))) + 1;
    117        1.1       jmc 
    118        1.1       jmc 	/*
    119        1.1       jmc 	 * Make sure at least the bus info block is in memory + the root dir
    120        1.1       jmc 	 * header quad. Add 1 here since offset is an array offset and size is
    121        1.1       jmc 	 * the total array size we want. If this is getting the root dir
    122        1.1       jmc 	 * then add another since infolen doesn't end on the root dir entry but
    123        1.1       jmc 	 * right before it.
    124        1.1       jmc 	 */
    125        1.9     perry 
    126        1.1       jmc 	if ((*size == 1) || (*size < (offset + 1))) {
    127        1.1       jmc 		*size = (crclen > infolen) ? crclen : infolen;
    128        1.1       jmc 		if (crclen == infolen)
    129        1.1       jmc 			(*size)++;
    130        1.1       jmc 		(*size)++;
    131        1.1       jmc 		return 0;
    132        1.1       jmc 	}
    133        1.1       jmc 
    134        1.1       jmc 	complete = 0;
    135        1.1       jmc 	numdirs = 0;
    136        1.1       jmc 	newlen = 0;
    137        1.9     perry 
    138        1.1       jmc 	while (!complete) {
    139        1.9     perry 
    140        1.1       jmc 		/*
    141        1.1       jmc 		 * Make sure the whole directory is in memory. If not, bail now
    142        1.1       jmc 		 * and read it in.
    143        1.1       jmc 		 */
    144        1.1       jmc 
    145        1.1       jmc 		newlen = P1212_DIRENT_GET_LEN((ntohl(t[offset])));
    146        1.1       jmc 		if ((offset + newlen + 1) > *size) {
    147        1.1       jmc 			newlen += offset + 1;
    148        1.1       jmc 			break;
    149        1.1       jmc 		}
    150        1.9     perry 
    151        1.1       jmc 		if (newlen == 0) {
    152        1.1       jmc 			DPRINTF(("Impossible directory length of 0!\n"));
    153        1.1       jmc 			return -1;
    154        1.1       jmc 		}
    155        1.1       jmc 
    156        1.1       jmc 		/*
    157        1.1       jmc 		 * Starting with the first byte of the directory, read through
    158        1.1       jmc 		 * and check the values found. On offsets and directories read
    159        1.1       jmc 		 * them in if appropriate (always for offsets, if not in memory
    160        1.1       jmc 		 * for leaf/directories).
    161        1.1       jmc 		 */
    162        1.1       jmc 
    163        1.1       jmc 		offset++;
    164        1.1       jmc 		len = newlen;
    165        1.1       jmc 		newlen = 0;
    166        1.1       jmc 		for (i = 0; i < len; i++) {
    167        1.2       jmc 			type = P1212_DIRENT_GET_KEYTYPE((ntohl(t[offset+i])));
    168        1.2       jmc 			val = P1212_DIRENT_GET_VALUE((ntohl(t[offset+i])));
    169        1.1       jmc 			switch (type) {
    170        1.1       jmc 			case P1212_KEYTYPE_Immediate:
    171        1.1       jmc 			case P1212_KEYTYPE_Offset:
    172        1.1       jmc 				break;
    173        1.1       jmc 			case P1212_KEYTYPE_Leaf:
    174        1.9     perry 
    175        1.1       jmc 				/*
    176        1.1       jmc 				 * If a leaf is found, and it's beyond the
    177        1.1       jmc 				 * current rom length and it's beyond the
    178        1.1       jmc 				 * current newlen setting,
    179        1.1       jmc 				 * then set newlen accordingly.
    180        1.1       jmc 				 */
    181        1.9     perry 
    182        1.1       jmc 				test = offset + i + val + 1;
    183        1.1       jmc 				if ((test > *size) && (test > newlen)) {
    184        1.1       jmc 					newlen = test;
    185        1.1       jmc 					break;
    186        1.1       jmc 				}
    187        1.9     perry 
    188        1.1       jmc 				/*
    189        1.1       jmc 				 * For leaf nodes just make sure the whole leaf
    190        1.1       jmc 				 * length is in the buffer. There's no data
    191        1.1       jmc 				 * inside of them that can refer to outside
    192        1.1       jmc 				 * nodes. (Uless it's vendor specific and then
    193        1.1       jmc 				 * you're on your own anyways).
    194        1.1       jmc 				 */
    195        1.1       jmc 
    196        1.1       jmc 				test--;
    197        1.9     perry 				infolen =
    198        1.2       jmc 				    P1212_DIRENT_GET_LEN((ntohl(t[test])));
    199        1.1       jmc 				test++;
    200        1.1       jmc 				test += infolen;
    201        1.1       jmc 				if ((test > *size) && (test > newlen)) {
    202        1.1       jmc 					newlen = test;
    203        1.1       jmc 				}
    204        1.1       jmc 				break;
    205        1.9     perry 
    206        1.1       jmc 			case P1212_KEYTYPE_Directory:
    207        1.9     perry 
    208        1.1       jmc 				/* Make sure the first quad is in memory. */
    209        1.9     perry 
    210        1.1       jmc 				test = offset + i + val + 1;
    211        1.1       jmc 				if ((test > *size) && (test > newlen)) {
    212        1.1       jmc 					newlen = test;
    213        1.1       jmc 					break;
    214        1.1       jmc 				}
    215        1.9     perry 
    216        1.1       jmc 				/*
    217        1.9     perry 				 * Can't just walk the ROM looking at type
    218        1.9     perry 				 * codes since these are only valid on
    219        1.2       jmc 				 * directory entries. So save any directories
    220        1.1       jmc 				 * we find into a queue and the bottom of the
    221        1.9     perry 				 * while loop will pop the last one off and
    222        1.2       jmc 				 * walk that directory.
    223        1.1       jmc 				 */
    224        1.9     perry 
    225        1.1       jmc 				test--;
    226        1.1       jmc 				dirs = realloc(dirs,
    227        1.1       jmc 				    sizeof(int) * (numdirs + 1), M_DEVBUF,
    228        1.1       jmc 				    M_WAITOK);
    229        1.1       jmc 				dirs[numdirs++] = test;
    230        1.1       jmc 				break;
    231        1.1       jmc 			default:
    232        1.1       jmc 				panic("Impossible type code: 0x%04hx",
    233        1.1       jmc 				    (unsigned short)type);
    234        1.1       jmc 				break;
    235        1.1       jmc 			}
    236        1.1       jmc 		}
    237        1.9     perry 
    238        1.1       jmc 		if (newlen) {
    239        1.1       jmc 			/* Cleanup. */
    240        1.9     perry 			if (dirs)
    241        1.1       jmc 				free(dirs, M_DEVBUF);
    242        1.1       jmc 			break;
    243        1.1       jmc 		}
    244        1.1       jmc 		if (dirs) {
    245        1.1       jmc 			offset = dirs[--numdirs];
    246        1.1       jmc 			dirs = realloc(dirs, sizeof(int) * numdirs, M_DEVBUF,
    247        1.1       jmc 			    M_WAITOK);
    248        1.1       jmc 		} else
    249        1.1       jmc 			complete = 1;
    250        1.1       jmc 	}
    251        1.9     perry 
    252        1.1       jmc 	if (newlen)
    253        1.1       jmc 		*size = newlen;
    254        1.1       jmc 	return 0;
    255        1.9     perry 
    256        1.1       jmc }
    257        1.1       jmc 
    258        1.1       jmc struct p1212_rom *
    259        1.1       jmc p1212_parse(u_int32_t *t, u_int32_t size, u_int32_t mask)
    260        1.1       jmc {
    261        1.1       jmc 
    262        1.1       jmc 	u_int16_t crc, romcrc, crc1;
    263        1.1       jmc 	u_int32_t next, check;
    264        1.1       jmc 	struct p1212_rom *rom;
    265        1.1       jmc 	int i;
    266        1.9     perry 
    267        1.1       jmc 	check = size;
    268        1.1       jmc 
    269        1.1       jmc 	if (p1212_iscomplete(t, &check) == -1) {
    270        1.1       jmc 		DPRINTF(("ROM is not complete\n"));
    271        1.1       jmc 		return NULL;
    272        1.1       jmc 	}
    273        1.1       jmc 	if (check != size) {
    274        1.1       jmc 		DPRINTF(("ROM is not complete (check != size)\n"));
    275        1.1       jmc 		return NULL;
    276        1.1       jmc 	}
    277        1.1       jmc 
    278        1.1       jmc 	/* Calculate both a good and known bad crc. */
    279        1.9     perry 
    280        1.1       jmc 	/* CRC's are calculated from everything except the first quad. */
    281        1.9     perry 
    282        1.9     perry 	crc = p1212_calc_crc(0, &t[1], P1212_ROMFMT_GET_CRCLEN((ntohl(t[0]))),
    283        1.1       jmc 		0);
    284        1.9     perry 
    285        1.1       jmc 	romcrc = P1212_ROMFMT_GET_CRC((ntohl(t[0])));
    286        1.1       jmc 	if (crc != romcrc) {
    287        1.1       jmc 		crc1 = p1212_calc_crc(0, &t[1],
    288        1.1       jmc 		    P1212_ROMFMT_GET_CRCLEN((ntohl(t[0]))), 1);
    289        1.1       jmc 		if (crc1 != romcrc) {
    290        1.1       jmc 			DPRINTF(("Invalid ROM: CRC: 0x%04hx, Calculated "
    291        1.1       jmc 			    "CRC: 0x%04hx, CRC1: 0x%04hx\n",
    292        1.1       jmc 			    (unsigned short)romcrc, (unsigned short)crc,
    293        1.1       jmc 			    (unsigned short)crc1));
    294        1.1       jmc 			return NULL;
    295        1.1       jmc 		}
    296        1.1       jmc 	}
    297        1.1       jmc 
    298        1.1       jmc 	/* Now, walk the ROM. */
    299        1.9     perry 
    300        1.1       jmc 	/* Get the initial offset for the root dir. */
    301        1.9     perry 
    302        1.9     perry 	rom = malloc(sizeof(struct p1212_rom), M_DEVBUF, M_WAITOK);
    303        1.1       jmc 	rom->len = P1212_ROMFMT_GET_INFOLEN((ntohl(t[0])));
    304        1.1       jmc 	next = rom->len + 1;
    305        1.1       jmc 
    306        1.1       jmc 	if ((rom->len < 1) || (rom->len > size)) {
    307        1.1       jmc 		DPRINTF(("Invalid ROM info length: %d\n", rom->len));
    308        1.1       jmc 		free(rom, M_DEVBUF);
    309        1.1       jmc 		return NULL;
    310        1.1       jmc 	}
    311        1.9     perry 
    312        1.1       jmc 	/* Exclude the quad which covers the bus name. */
    313        1.1       jmc 	rom->len--;
    314        1.1       jmc 
    315        1.1       jmc 	if (rom->len) {
    316        1.1       jmc 		rom->data = malloc(sizeof(u_int32_t) * rom->len, M_DEVBUF,
    317        1.1       jmc 		    M_WAITOK);
    318        1.2       jmc 		/* Add 2 to account for info/crc and bus name skipped. */
    319        1.1       jmc 		for (i = 0; i < rom->len; i++)
    320        1.1       jmc 			rom->data[i] = t[i + 2];
    321        1.1       jmc 	}
    322        1.1       jmc 
    323        1.1       jmc 	/* The name field is always 4 bytes and always the 2nd field. */
    324        1.1       jmc 	strncpy(rom->name, (char *)&t[1], 4);
    325        1.1       jmc 	rom->name[4] = 0;
    326        1.9     perry 
    327        1.1       jmc 	/*
    328        1.1       jmc 	 * Fill out the root directory. All these values are hardcoded so the
    329        1.1       jmc 	 * parse/print/match routines have a standard layout to work against.
    330        1.1       jmc 	 */
    331        1.9     perry 
    332        1.2       jmc 	rom->root = malloc(sizeof(*rom->root), M_DEVBUF, M_WAITOK|M_ZERO);
    333        1.1       jmc 	rom->root->com.key.key_type = P1212_KEYTYPE_Directory;
    334        1.1       jmc 	rom->root->com.key.key_value = 0;
    335        1.1       jmc 	rom->root->com.key.key = (u_int8_t)P1212_KEYTYPE_Directory;
    336        1.1       jmc 	rom->root->com.key.val = 0;
    337        1.1       jmc 	TAILQ_INIT(&rom->root->data_root);
    338        1.1       jmc 	TAILQ_INIT(&rom->root->subdir_root);
    339        1.9     perry 
    340        1.1       jmc 	if (p1212_parse_directory(rom->root, &t[next], mask)) {
    341        1.1       jmc 		DPRINTF(("Parse error in ROM. Bailing\n"));
    342        1.1       jmc 		p1212_free(rom);
    343        1.1       jmc 		return NULL;
    344        1.1       jmc 	}
    345        1.1       jmc 	return rom;
    346        1.1       jmc }
    347        1.1       jmc 
    348        1.1       jmc static int
    349        1.1       jmc p1212_parse_directory(struct p1212_dir *root, u_int32_t *addr, u_int32_t mask)
    350        1.1       jmc {
    351        1.1       jmc 	struct p1212_dir *dir, *sdir;
    352        1.1       jmc 	struct p1212_data *data;
    353        1.1       jmc 	struct p1212_com *com;
    354        1.1       jmc 	u_int32_t *t, desc;
    355        1.1       jmc 	u_int16_t crclen, crc, crc1, romcrc;
    356        1.1       jmc 	u_int8_t type, val;
    357        1.1       jmc 	unsigned long size;
    358        1.1       jmc 	int i, module_vendor_flag, module_sw_flag, node_sw_flag, unit_sw_flag;
    359        1.1       jmc 	int node_capabilities_flag, offset, unit_location_flag, unitdir_cnt;
    360        1.1       jmc 	int leafoff;
    361        1.9     perry 
    362        1.1       jmc 	t = addr;
    363        1.1       jmc 	dir = root;
    364        1.1       jmc 
    365        1.1       jmc 	module_vendor_flag = 0;
    366        1.1       jmc 	module_sw_flag = 0;
    367        1.1       jmc 	node_sw_flag = 0;
    368        1.1       jmc 	node_capabilities_flag = 0;
    369        1.1       jmc 	unitdir_cnt = 0;
    370        1.1       jmc 	offset = 0;
    371        1.1       jmc 
    372        1.9     perry 	while (dir) {
    373        1.1       jmc 		dir->match = 0;
    374        1.1       jmc 		crclen = P1212_DIRENT_GET_LEN((ntohl(t[offset])));
    375        1.1       jmc 		romcrc = P1212_DIRENT_GET_CRC((ntohl(t[offset])));
    376        1.9     perry 
    377        1.1       jmc 		crc = p1212_calc_crc(0, &t[offset + 1], crclen, 0);
    378        1.1       jmc 		if (crc != romcrc) {
    379        1.1       jmc 			crc1 = p1212_calc_crc(0, &t[offset + 1], crclen, 1);
    380        1.1       jmc 			if (crc1 != romcrc) {
    381        1.1       jmc 				DPRINTF(("Invalid ROM: CRC: 0x%04hx, "
    382        1.1       jmc 					    "Calculated CRC: "
    383        1.1       jmc 					    "0x%04hx, CRC1: 0x%04hx\n",
    384        1.1       jmc 					    (unsigned short)romcrc,
    385        1.1       jmc 					    (unsigned short)crc,
    386        1.1       jmc 					    (unsigned short)crc1));
    387        1.1       jmc 				return 1;
    388        1.1       jmc 			}
    389        1.1       jmc 		}
    390        1.1       jmc 		com = NULL;
    391        1.1       jmc 		unit_sw_flag = 0;
    392        1.1       jmc 		unit_location_flag = 0;
    393        1.1       jmc 		offset++;
    394        1.9     perry 
    395        1.1       jmc 		if ((dir->parent == NULL) && dir->com.key.val) {
    396        1.1       jmc 			DPRINTF(("Invalid root dir. key.val is 0x%0x and not"
    397        1.1       jmc 			    " 0x0\n", dir->com.key.val));
    398        1.1       jmc 			return 1;
    399        1.1       jmc 		}
    400        1.1       jmc 
    401        1.1       jmc 		for (i = offset; i < (offset + crclen); i++) {
    402        1.1       jmc 			desc = ntohl(t[i]);
    403        1.1       jmc 			type = P1212_DIRENT_GET_KEYTYPE(desc);
    404        1.1       jmc 			val = P1212_DIRENT_GET_KEYVALUE(desc);
    405        1.9     perry 
    406        1.1       jmc 			/*
    407        1.1       jmc 			 * Sanity check for valid types/locations/etc.
    408        1.1       jmc 			 *
    409        1.1       jmc 			 * See pages 79-100 of
    410        1.2       jmc 			 * ISO/IEC 13213:1194(ANSI/IEEE Std 1212, 1994 edition)
    411        1.1       jmc 			 * for specifics.
    412        1.1       jmc 			 *
    413        1.9     perry 			 * XXX: These all really should be broken out into
    414        1.1       jmc 			 * subroutines as it's grown large and complicated
    415        1.1       jmc 			 * in certain cases.
    416        1.1       jmc 			 */
    417        1.1       jmc 
    418        1.1       jmc 			switch (val) {
    419        1.1       jmc 			case P1212_KEYVALUE_Unit_Spec_Id:
    420        1.1       jmc 			case P1212_KEYVALUE_Unit_Sw_Version:
    421        1.1       jmc 			case P1212_KEYVALUE_Unit_Dependent_Info:
    422        1.1       jmc 			case P1212_KEYVALUE_Unit_Location:
    423        1.1       jmc 			case P1212_KEYVALUE_Unit_Poll_Mask:
    424        1.1       jmc 				if (dir->parent == NULL) {
    425        1.1       jmc 					DPRINTF(("Invalid ROM: %s is not "
    426        1.1       jmc 					    "valid in the root directory.\n",
    427        1.1       jmc 					    p1212_keyvalue_strings[val]));
    428        1.1       jmc 					return 1;
    429        1.1       jmc 				}
    430        1.1       jmc 				break;
    431        1.1       jmc 			default:
    432        1.1       jmc 				if (dir->com.key.val ==
    433        1.1       jmc 				    P1212_KEYVALUE_Unit_Directory) {
    434        1.1       jmc 					DPRINTF(("Invalid ROM: %s is "
    435        1.1       jmc 					    "not valid in a unit directory.\n",
    436        1.1       jmc 					    p1212_keyvalue_strings[val]));
    437        1.1       jmc 					return 1;
    438        1.1       jmc 				}
    439        1.1       jmc 				break;
    440        1.1       jmc 			}
    441        1.9     perry 
    442        1.1       jmc 			switch (type) {
    443        1.1       jmc 			case P1212_KEYTYPE_Immediate:
    444        1.1       jmc 				if (p1212_validate_immed(val, mask)) {
    445        1.1       jmc 					DPRINTF(("Invalid ROM: Can't have an "
    446        1.2       jmc 					    "immediate type with %s value. Key"
    447        1.2       jmc 					    " used at location 0x%0x in ROM\n",
    448        1.1       jmc 					    p1212_keyvalue_strings[val],
    449        1.1       jmc 					    (unsigned int)(&t[i]-&addr[0])));
    450        1.1       jmc 					return 1;
    451        1.1       jmc 				}
    452        1.1       jmc 				break;
    453        1.1       jmc 			case P1212_KEYTYPE_Offset:
    454        1.1       jmc 				if (p1212_validate_offset(val, mask)) {
    455        1.1       jmc 					DPRINTF(("Invalid ROM: Can't have "
    456        1.1       jmc 				            "an offset type with key %s."
    457        1.1       jmc 					    " Used at location 0x%0x in ROM\n",
    458        1.1       jmc 					    p1212_keyvalue_strings[val],
    459        1.1       jmc 					    (unsigned int)(&t[i]-&addr[0])));
    460        1.1       jmc 					return 1;
    461        1.1       jmc 				}
    462        1.1       jmc 				break;
    463        1.1       jmc 			case P1212_KEYTYPE_Leaf:
    464        1.1       jmc 				if (p1212_validate_leaf(val, mask)) {
    465        1.1       jmc 					DPRINTF(("Invalid ROM: Can't have a "
    466        1.1       jmc 					    "leaf type with %s value. Key "
    467        1.1       jmc 					    "used at location 0x%0x in ROM\n",
    468        1.1       jmc 					    p1212_keyvalue_strings[val],
    469        1.1       jmc 					    (unsigned int)(&t[i]-&addr[0])));
    470        1.1       jmc 					return 1;
    471        1.1       jmc 				}
    472        1.1       jmc 				break;
    473        1.1       jmc 			case P1212_KEYTYPE_Directory:
    474        1.1       jmc 				if (p1212_validate_dir(val, mask)) {
    475        1.1       jmc 					DPRINTF(("Invalid ROM: Can't have a "
    476        1.2       jmc 					    "directory type with %s value. Key"
    477        1.2       jmc 					    " used at location 0x%0x in ROM\n",
    478        1.1       jmc 					    p1212_keyvalue_strings[val],
    479        1.1       jmc 					    (unsigned int)(&t[i]-&addr[0])));
    480        1.1       jmc 					return 1;
    481        1.1       jmc 				}
    482        1.1       jmc 				break;
    483        1.1       jmc 			default:
    484        1.1       jmc 				panic("Impossible type code: 0x%04hx",
    485        1.1       jmc 				    (unsigned short)type);
    486        1.1       jmc 				break;
    487        1.1       jmc 			}
    488        1.9     perry 
    489        1.1       jmc 			/* Note flags for required fields. */
    490        1.1       jmc 
    491        1.1       jmc 			if (val == P1212_KEYVALUE_Module_Vendor_Id) {
    492        1.1       jmc 				module_vendor_flag = 1;
    493        1.1       jmc 			}
    494        1.1       jmc 
    495        1.1       jmc 			if (val == P1212_KEYVALUE_Node_Capabilities) {
    496        1.1       jmc 				node_capabilities_flag = 1;
    497        1.1       jmc 			}
    498        1.9     perry 
    499        1.1       jmc 			if (val == P1212_KEYVALUE_Unit_Sw_Version)
    500        1.1       jmc 				unit_sw_flag = 1;
    501        1.1       jmc 
    502        1.1       jmc 			if (val == P1212_KEYVALUE_Unit_Location)
    503        1.1       jmc 				unit_location_flag = 1;
    504        1.9     perry 
    505        1.1       jmc 			/*
    506        1.1       jmc 			 * This is just easier to spell out. You can't have
    507        1.1       jmc 			 * a module sw version if you include a node sw version
    508        1.1       jmc 			 * and vice-versa. Both aren't allowed if you have unit
    509        1.1       jmc 			 * dirs.
    510        1.1       jmc 			 */
    511        1.1       jmc 
    512        1.1       jmc 			if (val == P1212_KEYVALUE_Module_Sw_Version) {
    513        1.1       jmc 				if (node_sw_flag) {
    514        1.2       jmc 					DPRINTF(("Can't have a module software"
    515        1.2       jmc 				            " version along with a node "
    516        1.1       jmc 					    "software version entry\n"));
    517        1.1       jmc 					return 1;
    518        1.1       jmc 				}
    519        1.1       jmc 				if (unitdir_cnt) {
    520        1.1       jmc 					DPRINTF(("Can't have unit directories "
    521        1.1       jmc 					    "with module software version "
    522        1.1       jmc 					    "defined.\n"));
    523        1.1       jmc 					return 1;
    524        1.1       jmc 				}
    525        1.1       jmc 				module_sw_flag = 1;
    526        1.1       jmc 			}
    527        1.1       jmc 
    528        1.1       jmc 			if (val == P1212_KEYVALUE_Node_Sw_Version) {
    529        1.1       jmc 				if (module_sw_flag) {
    530        1.1       jmc 					DPRINTF(("Can't have a node software "
    531        1.1       jmc 				            "version along with a module "
    532        1.1       jmc 					    "software version entry\n"));
    533        1.1       jmc 					return 1;
    534        1.1       jmc 				}
    535        1.1       jmc 				if (unitdir_cnt) {
    536        1.1       jmc 					DPRINTF(("Can't have unit directories "
    537        1.1       jmc 					    "with node software version "
    538        1.1       jmc 					    "defined.\n"));
    539        1.1       jmc 					return 1;
    540        1.1       jmc 				}
    541        1.1       jmc 				node_sw_flag = 1;
    542        1.1       jmc 			}
    543        1.9     perry 
    544        1.1       jmc 			if (val == P1212_KEYVALUE_Unit_Directory) {
    545        1.1       jmc 				if (module_sw_flag || node_sw_flag) {
    546        1.1       jmc 					DPRINTF(("Can't have unit directories "
    547        1.1       jmc 					    "with either module or node "
    548        1.1       jmc 					    "software version defined.\n"));
    549        1.1       jmc 					return 1;
    550        1.1       jmc 				}
    551        1.1       jmc 				unitdir_cnt++;
    552        1.1       jmc 			}
    553        1.9     perry 
    554        1.1       jmc 			/*
    555        1.1       jmc 			 * Text descriptors are special. They describe the
    556        1.1       jmc 			 * last entry they follow. So they need to be included
    557        1.1       jmc 			 * with it's struct and there's nothing in the spec
    558        1.1       jmc 			 * preventing one from putting text descriptors after
    559        1.1       jmc 			 * directory descriptors. Also they can be a single
    560        1.1       jmc 			 * value or a list of them in a directory format so
    561        1.9     perry 			 * account for either. Finally if they're in a
    562        1.9     perry 			 * directory those can be the only types in a
    563        1.2       jmc 			 * directory.
    564        1.1       jmc 			 */
    565        1.1       jmc 
    566        1.1       jmc 			if (val == P1212_KEYVALUE_Textual_Descriptor) {
    567        1.1       jmc 
    568        1.1       jmc 				size = sizeof(struct p1212_textdata *);
    569        1.1       jmc 				leafoff = P1212_DIRENT_GET_VALUE(desc);
    570        1.1       jmc 				leafoff += i;
    571        1.1       jmc 
    572        1.1       jmc 				if (com == NULL) {
    573        1.2       jmc 					DPRINTF(("Can't have a text descriptor"
    574        1.2       jmc 					    " as the first entry in a "
    575        1.1       jmc 					    "directory\n"));
    576        1.1       jmc 					return 1;
    577        1.1       jmc 				}
    578        1.1       jmc 
    579        1.1       jmc 				if (com->textcnt != 0) {
    580        1.1       jmc 					DPRINTF(("Text descriptors can't "
    581        1.1       jmc 					    "follow each other in a "
    582        1.1       jmc 					    "directory\n"));
    583        1.1       jmc 					return 1;
    584        1.1       jmc 				}
    585        1.1       jmc 
    586        1.1       jmc 				if (type == P1212_KEYTYPE_Leaf) {
    587        1.1       jmc 					com->text =
    588        1.1       jmc 					    malloc(size, M_DEVBUF, M_WAITOK);
    589        1.1       jmc 					com->text[0] =
    590        1.1       jmc 					    p1212_parse_text_desc(&t[leafoff]);
    591        1.1       jmc 					if (com->text[0] == NULL) {
    592        1.2       jmc 						DPRINTF(("Got an error parsing"
    593        1.2       jmc 						    " text descriptor at "
    594        1.2       jmc 						    "offset 0x%0x\n",
    595        1.1       jmc 						    &t[leafoff]-&addr[0]));
    596        1.1       jmc 						free(com->text, M_DEVBUF);
    597        1.1       jmc 						return 1;
    598        1.1       jmc 					}
    599        1.1       jmc 					com->textcnt = 1;
    600        1.1       jmc 				} else {
    601        1.9     perry 					i = p1212_parse_textdir(com,
    602        1.1       jmc 						&t[leafoff]);
    603        1.1       jmc 					if (i)
    604        1.1       jmc 						return 1;
    605        1.1       jmc 				}
    606        1.1       jmc 			}
    607        1.1       jmc 
    608        1.1       jmc 			if ((type != P1212_KEYTYPE_Directory) &&
    609        1.1       jmc 			    (val != P1212_KEYVALUE_Textual_Descriptor)) {
    610        1.1       jmc 				data = malloc(sizeof(struct p1212_data),
    611        1.1       jmc 				    M_DEVBUF, M_WAITOK|M_ZERO);
    612        1.1       jmc 				data->com.key.key_type = type;
    613        1.1       jmc 				data->com.key.key_value = val;
    614        1.1       jmc 				data->com.key.key =
    615        1.1       jmc 				    P1212_DIRENT_GET_KEY((ntohl(t[i])));
    616        1.1       jmc 				data->com.key.val =
    617        1.1       jmc 				    P1212_DIRENT_GET_VALUE((ntohl(t[i])));
    618        1.1       jmc 				com = &data->com;
    619        1.1       jmc 
    620        1.9     perry 				/*
    621        1.1       jmc 				 * Don't try and read the offset. It may be
    622        1.1       jmc 				 * a register or something special. Generally
    623        1.1       jmc 				 * these are node specific so let the upper
    624        1.1       jmc 				 * level code figure it out.
    625        1.1       jmc 				 */
    626        1.1       jmc 
    627        1.1       jmc 				if ((type == P1212_KEYTYPE_Immediate) ||
    628        1.9     perry 				    (type == P1212_KEYTYPE_Offset))
    629        1.1       jmc 					data->val = data->com.key.val;
    630        1.9     perry 
    631        1.1       jmc 				data->leafdata = NULL;
    632        1.1       jmc 				TAILQ_INSERT_TAIL(&dir->data_root, data, data);
    633        1.9     perry 
    634        1.1       jmc 				if (type == P1212_KEYTYPE_Leaf) {
    635        1.1       jmc 					leafoff = i + data->com.key.val;
    636        1.1       jmc 					data->leafdata =
    637        1.1       jmc 					    p1212_parse_leaf(&t[leafoff]);
    638        1.1       jmc 					if (data->leafdata == NULL) {
    639        1.1       jmc 						DPRINTF(("Error parsing leaf\n"));
    640        1.1       jmc 						return 1;
    641        1.1       jmc 					}
    642        1.1       jmc 				}
    643        1.9     perry 			}
    644        1.1       jmc 			if (type == P1212_KEYTYPE_Directory) {
    645        1.9     perry 
    646        1.9     perry 				sdir = malloc(sizeof(struct p1212_dir),
    647        1.1       jmc 					M_DEVBUF, M_WAITOK|M_ZERO);
    648        1.1       jmc 				sdir->parent = dir;
    649        1.1       jmc 				sdir->com.key.key_type = type;
    650        1.1       jmc 				sdir->com.key.key_value = val;
    651        1.1       jmc 				sdir->com.key.key =
    652        1.1       jmc 				    P1212_DIRENT_GET_KEY((ntohl(t[i])));
    653        1.1       jmc 				sdir->com.key.val =
    654        1.1       jmc 				    P1212_DIRENT_GET_VALUE((ntohl(t[i])));
    655        1.1       jmc 				com = &sdir->com;
    656        1.1       jmc 				sdir->match = sdir->com.key.val + i;
    657        1.1       jmc 				TAILQ_INIT(&sdir->data_root);
    658        1.1       jmc 				TAILQ_INIT(&sdir->subdir_root);
    659        1.2       jmc 				TAILQ_INSERT_TAIL(&dir->subdir_root, sdir,dir);
    660        1.1       jmc 			}
    661        1.1       jmc 		}
    662        1.1       jmc 
    663        1.1       jmc 		/* More validity checks. */
    664        1.1       jmc 
    665        1.1       jmc 		if (dir->parent == NULL) {
    666        1.1       jmc 			if (module_vendor_flag == 0) {
    667        1.1       jmc 				DPRINTF(("Missing module vendor entry in root "
    668        1.1       jmc 				    "directory.\n"));
    669        1.1       jmc 				return 1;
    670        1.1       jmc 			}
    671        1.1       jmc 			if (node_capabilities_flag == 0) {
    672        1.1       jmc 				DPRINTF(("Missing node capabilities entry in "
    673        1.1       jmc 				    "root directory.\n"));
    674        1.1       jmc 				return 1;
    675        1.1       jmc 			}
    676        1.1       jmc 		} else {
    677        1.1       jmc 			if ((unitdir_cnt > 1) && (unit_location_flag == 0)) {
    678        1.1       jmc 				DPRINTF(("Must have a unit location in each "
    679        1.1       jmc 				    "unit directory when more than one unit "
    680        1.1       jmc 				    "directory exists.\n"));
    681        1.1       jmc 				return 1;
    682        1.1       jmc 			}
    683        1.1       jmc 		}
    684        1.1       jmc 
    685        1.1       jmc 		/*
    686        1.1       jmc 		 * Ok, done with this directory and it's sanity checked. Now
    687        1.1       jmc 		 * loop through and either find an unparsed subdir or one
    688        1.1       jmc 		 * farther back up the chain.
    689        1.1       jmc 		 */
    690        1.1       jmc 
    691        1.1       jmc 		if (!TAILQ_EMPTY(&dir->subdir_root)) {
    692        1.1       jmc 			sdir = TAILQ_FIRST(&dir->subdir_root);
    693        1.1       jmc 		} else {
    694        1.1       jmc 			do {
    695        1.1       jmc 				sdir = TAILQ_NEXT(dir, dir);
    696        1.1       jmc 				if (sdir == NULL) {
    697        1.1       jmc 					dir = dir->parent;
    698        1.1       jmc 				}
    699        1.1       jmc 			} while ((sdir == NULL) && (dir != NULL));
    700        1.1       jmc 		}
    701        1.1       jmc 		if (dir) {
    702        1.1       jmc 			dir = sdir;
    703        1.1       jmc 			if (!dir->match) {
    704        1.1       jmc 				DPRINTF(("Invalid subdir..Has no offset\n"));
    705        1.1       jmc 				return 1;
    706        1.1       jmc 			}
    707        1.1       jmc 			offset = dir->match;
    708        1.1       jmc 		}
    709        1.1       jmc 	}
    710        1.1       jmc 	return 0;
    711        1.1       jmc }
    712        1.1       jmc 
    713        1.1       jmc static struct p1212_leafdata *
    714        1.1       jmc p1212_parse_leaf(u_int32_t *t)
    715        1.1       jmc {
    716        1.1       jmc 	u_int16_t crclen, crc, crc1, romcrc;
    717        1.1       jmc 	struct p1212_leafdata *leafdata;
    718        1.1       jmc 	int i;
    719        1.1       jmc 
    720        1.1       jmc 	crclen = P1212_DIRENT_GET_LEN((ntohl(t[0])));
    721        1.1       jmc 	romcrc = P1212_DIRENT_GET_CRC((ntohl(t[0])));
    722        1.1       jmc 	crc = p1212_calc_crc(0, &t[1], crclen, 0);
    723        1.1       jmc 	crc1 = p1212_calc_crc(0,&t[1], crclen, 1);
    724        1.1       jmc 	if ((crc != romcrc) && (crc1 != romcrc)) {
    725        1.1       jmc 		DPRINTF(("Invalid ROM: CRC: 0x%04hx, Calculated CRC: "
    726        1.1       jmc 		    "0x%04hx, CRC1: 0x%04hx\n", (unsigned short)romcrc,
    727        1.1       jmc 		    (unsigned short)crc, (unsigned short)crc1));
    728        1.1       jmc 		return NULL;
    729        1.1       jmc 	}
    730        1.1       jmc 	t++;
    731        1.9     perry 
    732        1.1       jmc 	/*
    733        1.1       jmc 	 * Most of these are vendor specific so don't bother trying to map them
    734        1.1       jmc 	 * out. Anything which needs them later on can extract them.
    735        1.1       jmc 	 */
    736        1.1       jmc 
    737        1.1       jmc 	leafdata = malloc(sizeof(struct p1212_leafdata), M_DEVBUF, M_WAITOK);
    738        1.1       jmc 	leafdata->data = malloc((sizeof(u_int32_t) * crclen), M_DEVBUF,
    739        1.1       jmc 	    M_WAITOK);
    740        1.1       jmc 	leafdata->len = crclen;
    741        1.1       jmc 	for (i = 0; i < crclen; i++)
    742        1.2       jmc 		leafdata->data[i] = ntohl(t[i]);
    743        1.1       jmc 	return leafdata;
    744        1.1       jmc }
    745        1.1       jmc 
    746        1.1       jmc static int
    747        1.1       jmc p1212_parse_textdir(struct p1212_com *com, u_int32_t *addr)
    748        1.1       jmc {
    749        1.1       jmc 	u_int32_t *t, entry, new;
    750        1.1       jmc 	u_int16_t crclen, crc, crc1, romcrc;
    751        1.1       jmc 	u_int8_t type, val;
    752        1.1       jmc 	int i, size;
    753        1.1       jmc 
    754        1.1       jmc 	/*
    755        1.1       jmc 	 * A bit more complicated. A directory for a text descriptor can
    756        1.1       jmc 	 * contain text descriptor leaf nodes only.
    757        1.1       jmc 	 */
    758        1.9     perry 
    759        1.1       jmc 	com->text = NULL;
    760        1.1       jmc 	size = sizeof(struct p1212_text *);
    761        1.7      fvdl 	t = addr;
    762        1.9     perry 
    763        1.1       jmc 	crclen = P1212_DIRENT_GET_LEN((ntohl(t[0])));
    764        1.1       jmc 	romcrc = P1212_DIRENT_GET_CRC((ntohl(t[0])));
    765        1.1       jmc 	crc = p1212_calc_crc(0, &t[1], crclen, 0);
    766        1.1       jmc 	crc1 = p1212_calc_crc(0,&t[1], crclen, 1);
    767        1.1       jmc 	if ((crc != romcrc) && (crc1 != romcrc)) {
    768        1.1       jmc 		DPRINTF(("Invalid ROM: CRC: 0x%04hx, Calculated CRC: "
    769        1.1       jmc 			    "0x%04hx, CRC1: 0x%04hx\n", (unsigned short)romcrc,
    770        1.1       jmc 			    (unsigned short)crc, (unsigned short)crc1));
    771        1.1       jmc 		return 1;
    772        1.1       jmc 	}
    773        1.1       jmc 	t++;
    774        1.1       jmc 	for (i = 0; i < crclen; i++) {
    775        1.1       jmc 		entry = ntohl(t[i]);
    776        1.9     perry 
    777        1.1       jmc 		type = P1212_DIRENT_GET_KEYTYPE(entry);
    778        1.1       jmc 		val = P1212_DIRENT_GET_KEYVALUE(entry);
    779        1.1       jmc 		if ((type != P1212_KEYTYPE_Leaf) ||
    780        1.1       jmc 		    (val != P1212_KEYVALUE_Textual_Descriptor)) {
    781        1.1       jmc 			DPRINTF(("Text descriptor directories can only "
    782        1.1       jmc 			    "contain text descriptors. Type: %s, value: %s "
    783        1.1       jmc 			    "isn't valid at offset 0x%0x\n",
    784        1.1       jmc 			    p1212_keytype_strings[type],
    785        1.1       jmc 			    p1212_keyvalue_strings[val], &t[i]-&addr[0]));
    786        1.1       jmc 			return 1;
    787        1.1       jmc 		}
    788        1.9     perry 
    789        1.1       jmc 		new = P1212_DIRENT_GET_VALUE(entry);
    790        1.1       jmc 		com->text = realloc(com->text, size * (com->textcnt + 1),
    791        1.1       jmc 		    M_DEVBUF, M_WAITOK);
    792        1.1       jmc 		if ((com->text[i] = p1212_parse_text_desc(&t[i+new])) == NULL) {
    793        1.1       jmc 			DPRINTF(("Got an error parsing text descriptor.\n"));
    794        1.1       jmc 			if (com->textcnt == 0)
    795        1.1       jmc 				free(com->text, M_DEVBUF);
    796        1.1       jmc 			return 1;
    797        1.1       jmc 		}
    798        1.1       jmc 		com->textcnt++;
    799        1.1       jmc 	}
    800        1.1       jmc 	return 0;
    801        1.1       jmc }
    802        1.1       jmc 
    803        1.1       jmc static struct p1212_textdata *
    804        1.1       jmc p1212_parse_text_desc(u_int32_t *addr)
    805        1.1       jmc {
    806        1.1       jmc 	u_int32_t *t;
    807        1.1       jmc 	u_int16_t crclen, crc, crc1, romcrc;
    808        1.1       jmc 	struct p1212_textdata *text;
    809        1.1       jmc 	int size;
    810        1.9     perry 
    811        1.1       jmc 	t = addr;
    812        1.9     perry 
    813        1.1       jmc 	crclen = P1212_DIRENT_GET_LEN((ntohl(t[0])));
    814        1.1       jmc 	romcrc = P1212_DIRENT_GET_CRC((ntohl(t[0])));
    815        1.9     perry 
    816        1.1       jmc 	if (crclen < P1212_TEXT_Min_Leaf_Length) {
    817        1.1       jmc 		DPRINTF(("Invalid ROM: text descriptor too short\n"));
    818        1.1       jmc 		return NULL;
    819        1.1       jmc 	}
    820        1.1       jmc 
    821        1.1       jmc 	crc = p1212_calc_crc(0, &t[1], crclen, 0);
    822        1.1       jmc 	if (crc != romcrc) {
    823        1.1       jmc 		crc1 = p1212_calc_crc(0, &t[1], crclen, 1);
    824        1.1       jmc 		if (crc1 != romcrc) {
    825        1.1       jmc 			DPRINTF(("Invalid ROM: CRC: 0x%04hx, Calculated CRC: "
    826        1.1       jmc 		            "0x%04hx, CRC1: 0x%04hx\n", (unsigned short)romcrc,
    827        1.1       jmc 			    (unsigned short)crc, (unsigned short)crc1));
    828        1.1       jmc 			return NULL;
    829        1.1       jmc 		}
    830        1.1       jmc 	}
    831        1.1       jmc 
    832        1.1       jmc 	t++;
    833        1.1       jmc 	text = malloc(sizeof(struct p1212_textdata), M_DEVBUF, M_WAITOK);
    834        1.1       jmc 	text->spec_type = P1212_TEXT_GET_Spec_Type((ntohl(t[0])));
    835        1.1       jmc 	text->spec_id = P1212_TEXT_GET_Spec_Id((ntohl(t[0])));
    836        1.1       jmc 	text->lang_id = ntohl(t[1]);
    837        1.1       jmc 
    838        1.1       jmc 	t++;
    839        1.1       jmc 	t++;
    840        1.1       jmc 	crclen -= 2;
    841        1.2       jmc 	size = (crclen * sizeof(u_int32_t));
    842        1.1       jmc 
    843        1.2       jmc 	text->text = malloc(size + 1, M_DEVBUF, M_WAITOK|M_ZERO);
    844        1.1       jmc 
    845        1.1       jmc 	memcpy(text->text, &t[0], size);
    846        1.1       jmc 
    847        1.1       jmc 	return text;
    848        1.1       jmc }
    849        1.1       jmc 
    850        1.1       jmc struct p1212_key **
    851        1.1       jmc p1212_find(struct p1212_dir *root, int type, int value, int flags)
    852        1.1       jmc {
    853        1.1       jmc 	struct p1212_key **retkeys;
    854        1.1       jmc 	struct p1212_dir *dir, *sdir, *parent;
    855        1.1       jmc 	struct p1212_data *data;
    856        1.1       jmc 	int numkeys;
    857        1.1       jmc 
    858        1.1       jmc 	numkeys = 0;
    859        1.1       jmc 	retkeys = NULL;
    860        1.9     perry 
    861        1.1       jmc 	if ((type < P1212_KEYTYPE_Immediate) ||
    862        1.1       jmc 	    (type > P1212_KEYTYPE_Directory)) {
    863        1.1       jmc #ifdef DIAGNOSTIC
    864        1.1       jmc 		printf("p1212_find: invalid type - %d\n", type);
    865        1.1       jmc #endif
    866        1.1       jmc 		return NULL;
    867        1.1       jmc 	}
    868        1.1       jmc 
    869        1.1       jmc 	if ((value < -1) ||
    870        1.1       jmc 	    (value > (sizeof(p1212_keyvalue_strings) / sizeof(char *)))) {
    871        1.1       jmc #ifdef DIAGNOSTIC
    872        1.1       jmc 		printf("p1212_find: invalid value - %d\n", value);
    873        1.1       jmc #endif
    874        1.1       jmc 		return NULL;
    875        1.1       jmc 	}
    876        1.9     perry 
    877        1.1       jmc 	if (flags & ~(P1212_FIND_SEARCHALL | P1212_FIND_RETURNALL)) {
    878        1.1       jmc #ifdef DIAGNOSTIC
    879        1.1       jmc 		printf("p1212_find: invalid flags - %d\n", flags);
    880        1.1       jmc #endif
    881        1.1       jmc 		return NULL;
    882        1.1       jmc 	}
    883        1.1       jmc 
    884        1.1       jmc 	/*
    885        1.1       jmc 	 * Part of this is copied from p1212_walk to do depth first traversal
    886        1.1       jmc 	 * without using recursion. Using the walk API would have made things
    887        1.1       jmc 	 * more complicated in trying to build up the return struct otherwise.
    888        1.1       jmc 	 */
    889        1.9     perry 
    890        1.1       jmc 	dir = root;
    891        1.1       jmc 	sdir = NULL;
    892        1.1       jmc 
    893        1.1       jmc 	parent = root->parent;
    894        1.1       jmc 	root->parent = NULL;
    895        1.1       jmc 
    896        1.1       jmc 	while (dir) {
    897        1.1       jmc 		if (type == P1212_KEYTYPE_Directory) {
    898        1.1       jmc 			TAILQ_FOREACH(sdir, &dir->subdir_root, dir) {
    899        1.1       jmc 				if ((sdir->com.key.key_value == value) ||
    900        1.1       jmc 				    (value == -1)) {
    901        1.1       jmc 					numkeys++;
    902        1.1       jmc 					retkeys = realloc(retkeys,
    903        1.1       jmc 					    sizeof(struct p1212_key *) *
    904        1.4    ichiro 					    (numkeys + 1), M_DEVBUF, M_WAITOK);
    905        1.1       jmc 					retkeys[numkeys - 1] = &sdir->com.key;
    906        1.1       jmc 					retkeys[numkeys] = NULL;
    907        1.1       jmc 					if ((flags & P1212_FIND_RETURNALL)
    908        1.1       jmc 					    == 0) {
    909        1.1       jmc 						root->parent = parent;
    910        1.1       jmc 						return retkeys;
    911        1.1       jmc 					}
    912        1.1       jmc 				}
    913        1.1       jmc 			}
    914        1.1       jmc 		} else {
    915        1.1       jmc 			TAILQ_FOREACH(data, &dir->data_root, data) {
    916        1.1       jmc 				if (((data->com.key.key_type == type) &&
    917        1.1       jmc 				     (data->com.key.key_value == value)) ||
    918        1.1       jmc 				    ((data->com.key.key_type == type) &&
    919        1.1       jmc 				     (value == -1))) {
    920        1.1       jmc 					numkeys++;
    921        1.1       jmc 					retkeys = realloc(retkeys,
    922        1.1       jmc 					    sizeof(struct p1212_key *) *
    923        1.4    ichiro 					    (numkeys + 1), M_DEVBUF, M_WAITOK);
    924        1.1       jmc 					retkeys[numkeys - 1] = &data->com.key;
    925        1.1       jmc 					retkeys[numkeys] = NULL;
    926        1.1       jmc 					if ((flags & P1212_FIND_RETURNALL)
    927        1.1       jmc 					    == 0) {
    928        1.1       jmc 						root->parent = parent;
    929        1.1       jmc 						return retkeys;
    930        1.1       jmc 					}
    931        1.1       jmc 				}
    932        1.1       jmc 			}
    933        1.1       jmc 		}
    934        1.1       jmc 		if (flags & P1212_FIND_SEARCHALL) {
    935        1.1       jmc 			do {
    936        1.1       jmc 				sdir = TAILQ_NEXT(dir, dir);
    937        1.1       jmc 				if (sdir == NULL) {
    938        1.1       jmc 					dir = dir->parent;
    939        1.1       jmc 				}
    940        1.1       jmc 			} while ((sdir == NULL) && (dir != NULL));
    941        1.1       jmc 			dir = sdir;
    942        1.1       jmc 		} else
    943        1.1       jmc 			dir = NULL;
    944        1.1       jmc 	}
    945        1.1       jmc 	root->parent = parent;
    946        1.1       jmc 	return retkeys;
    947        1.1       jmc }
    948        1.1       jmc 
    949        1.9     perry void
    950        1.1       jmc p1212_walk(struct p1212_dir *root, void *arg,
    951        1.1       jmc     void (*func)(struct p1212_key *, void *))
    952        1.1       jmc {
    953        1.1       jmc 	struct p1212_data *data;
    954        1.1       jmc 	struct p1212_dir *sdir, *dir, *parent;
    955        1.1       jmc 
    956        1.1       jmc 	dir = root;
    957        1.1       jmc 	sdir = NULL;
    958        1.1       jmc 
    959        1.1       jmc 	if (func == NULL) {
    960        1.1       jmc #ifdef DIAGNOSTIC
    961        1.1       jmc 		printf("p1212_walk: Passed in NULL function\n");
    962        1.1       jmc #endif
    963        1.1       jmc 		return;
    964        1.1       jmc 	}
    965        1.1       jmc 	if (root == NULL) {
    966        1.1       jmc #ifdef DIAGNOSTIC
    967        1.1       jmc 		printf("p1212_walk: Called with NULL root\n");
    968        1.1       jmc #endif
    969        1.1       jmc 		return;
    970        1.1       jmc 	}
    971        1.9     perry 
    972        1.1       jmc 	/* Allow walking from any point. Just mark the starting point. */
    973        1.1       jmc 	parent = root->parent;
    974        1.1       jmc 	root->parent = NULL;
    975        1.9     perry 
    976        1.1       jmc 	/*
    977        1.1       jmc 	 * Depth first traversal that doesn't use recursion.
    978        1.1       jmc 	 *
    979        1.1       jmc 	 * Call the function first for the directory node and then loop through
    980        1.1       jmc 	 * all the data nodes and call the function for them.
    981        1.1       jmc 	 *
    982        1.1       jmc 	 * Finally, figure out the next possible directory node if one is
    983        1.1       jmc 	 * available or bail out.
    984        1.1       jmc 	 */
    985        1.1       jmc 
    986        1.1       jmc 	while (dir) {
    987        1.1       jmc 		func((struct p1212_key *) dir, arg);
    988        1.9     perry 		TAILQ_FOREACH(data, &dir->data_root, data)
    989        1.1       jmc 			func((struct p1212_key *) data, arg);
    990        1.1       jmc 		if (!TAILQ_EMPTY(&dir->subdir_root)) {
    991        1.1       jmc 			sdir = TAILQ_FIRST(&dir->subdir_root);
    992        1.1       jmc 		} else {
    993        1.1       jmc 			do {
    994        1.1       jmc 				sdir = TAILQ_NEXT(dir, dir);
    995        1.1       jmc 				if (sdir == NULL) {
    996        1.1       jmc 					dir = dir->parent;
    997        1.1       jmc 				}
    998        1.1       jmc 			} while ((sdir == NULL) && dir);
    999        1.1       jmc 		}
   1000        1.1       jmc 		dir = sdir;
   1001        1.9     perry 	}
   1002        1.1       jmc 
   1003        1.1       jmc 	root->parent = parent;
   1004        1.1       jmc }
   1005        1.1       jmc 
   1006        1.1       jmc void
   1007        1.1       jmc p1212_print(struct p1212_dir *dir)
   1008        1.1       jmc {
   1009        1.1       jmc 	int indent;
   1010        1.9     perry 
   1011        1.1       jmc 	indent = 0;
   1012        1.9     perry 
   1013        1.1       jmc 	p1212_walk(dir, &indent, p1212_print_node);
   1014        1.1       jmc 	printf("\n");
   1015        1.1       jmc }
   1016        1.9     perry 
   1017        1.1       jmc static void
   1018        1.1       jmc p1212_print_node(struct p1212_key *key, void *arg)
   1019        1.1       jmc {
   1020        1.9     perry 
   1021        1.1       jmc 	struct p1212_data *data;
   1022        1.1       jmc 	struct p1212_dir *sdir, *dir;
   1023        1.1       jmc 	int i, j, *indent;
   1024        1.1       jmc 
   1025        1.1       jmc 	indent = arg;
   1026        1.1       jmc 
   1027        1.1       jmc 	if (key->key_type == P1212_KEYTYPE_Directory) {
   1028        1.1       jmc 		dir = (struct p1212_dir *) key;
   1029        1.1       jmc 		data = NULL;
   1030        1.1       jmc 	} else {
   1031        1.1       jmc 		data = (struct p1212_data *) key;
   1032        1.1       jmc 		dir = NULL;
   1033        1.1       jmc 	}
   1034        1.1       jmc 
   1035        1.1       jmc 	/* Recompute the indent level on each directory. */
   1036        1.1       jmc 	if (dir) {
   1037        1.1       jmc 		*indent = 0;
   1038        1.1       jmc 		sdir = dir->parent;
   1039        1.1       jmc 		while (sdir != NULL) {
   1040        1.1       jmc 			(*indent)++;
   1041        1.1       jmc 			sdir = sdir->parent;
   1042        1.1       jmc 		}
   1043        1.1       jmc 	}
   1044        1.1       jmc 
   1045        1.1       jmc 	if (dir && dir->parent)
   1046        1.1       jmc 		printf("\n");
   1047        1.1       jmc 
   1048        1.1       jmc 	/* Set the indent string up. 4 spaces per level. */
   1049        1.1       jmc 	for (i = 0; i < (*indent * 4); i++)
   1050        1.1       jmc 		printf(" ");
   1051        1.9     perry 
   1052        1.1       jmc 	if (dir) {
   1053        1.1       jmc 		printf("Directory: ");
   1054        1.1       jmc 		if (dir->print)
   1055        1.1       jmc 			dir->print(dir);
   1056        1.1       jmc 		else {
   1057        1.1       jmc 			if (key->key_value >=
   1058        1.9     perry 			    (sizeof(p1212_keyvalue_strings) / sizeof(char *)))
   1059        1.1       jmc 				printf("Unknown type 0x%04hx\n",
   1060        1.1       jmc 				    (unsigned short)key->key_value);
   1061        1.1       jmc 			else
   1062        1.1       jmc 				printf("%s\n",
   1063        1.1       jmc 				    p1212_keyvalue_strings[key->key_value]);
   1064        1.1       jmc 		}
   1065        1.1       jmc 		if (dir->com.textcnt) {
   1066        1.1       jmc 			for (i = 0; i < dir->com.textcnt; i++) {
   1067        1.1       jmc 				for (j = 0; j < (*indent * 4); j++)
   1068        1.1       jmc 					printf(" ");
   1069        1.1       jmc 				printf("Text descriptor: %s\n",
   1070        1.1       jmc 				    dir->com.text[i]->text);
   1071        1.1       jmc 			}
   1072        1.1       jmc 		}
   1073        1.1       jmc 		printf("\n");
   1074        1.1       jmc 	} else {
   1075        1.1       jmc 		if (data->print)
   1076        1.1       jmc 			data->print(data);
   1077        1.1       jmc 		else {
   1078        1.1       jmc 			if (key->key_value >=
   1079        1.9     perry 			    (sizeof(p1212_keyvalue_strings) / sizeof(char *)))
   1080        1.1       jmc 				printf("Unknown type 0x%04hx: ",
   1081        1.1       jmc 				    (unsigned short)key->key_value);
   1082        1.1       jmc 			else
   1083        1.1       jmc 				printf("%s: ",
   1084        1.1       jmc 				    p1212_keyvalue_strings[key->key_value]);
   1085        1.1       jmc 
   1086        1.1       jmc 			printf("0x%08x\n", key->val);
   1087        1.1       jmc #ifdef DIAGNOSTIC
   1088        1.1       jmc 			if ((data->com.key.key_type == P1212_KEYTYPE_Leaf) &&
   1089        1.9     perry 			    (data->leafdata == NULL))
   1090        1.1       jmc 				panic("Invalid data node in configrom tree");
   1091        1.1       jmc #endif
   1092        1.9     perry 
   1093        1.1       jmc 			if (data->leafdata) {
   1094        1.1       jmc 				for (i = 0; i < data->leafdata->len; i++) {
   1095        1.1       jmc 					for (j = 0; j < (*indent * 4); j++)
   1096        1.1       jmc 						printf(" ");
   1097        1.1       jmc 					printf ("Leaf data: 0x%08x\n",
   1098        1.1       jmc 					    data->leafdata->data[i]);
   1099        1.1       jmc 				}
   1100        1.1       jmc 			}
   1101        1.9     perry 			if (data->com.textcnt)
   1102        1.1       jmc 				for (i = 0; i < data->com.textcnt; i++) {
   1103        1.1       jmc 					for (j = 0; j < (*indent * 4); j++)
   1104        1.1       jmc 						printf(" ");
   1105        1.1       jmc 					printf("Text descriptor: %s\n",
   1106        1.1       jmc 					    data->com.text[i]->text);
   1107        1.1       jmc 				}
   1108        1.9     perry 
   1109        1.1       jmc 		}
   1110        1.1       jmc 	}
   1111        1.1       jmc }
   1112        1.1       jmc 
   1113        1.1       jmc 
   1114        1.1       jmc void
   1115        1.1       jmc p1212_free(struct p1212_rom *rom)
   1116        1.1       jmc {
   1117        1.1       jmc 	struct p1212_dir *sdir, *dir;
   1118        1.1       jmc 	struct p1212_data *data;
   1119        1.1       jmc 	int i;
   1120        1.1       jmc 
   1121        1.1       jmc 	dir = rom->root;
   1122        1.9     perry 
   1123        1.1       jmc 	/* Avoid recursing. Find the bottom most node and work back. */
   1124        1.1       jmc 	while (dir) {
   1125        1.1       jmc 		if (!TAILQ_EMPTY(&dir->subdir_root)) {
   1126        1.1       jmc 			sdir = TAILQ_FIRST(&dir->subdir_root);
   1127        1.1       jmc 			if (TAILQ_EMPTY(&sdir->subdir_root)) {
   1128        1.1       jmc 				TAILQ_REMOVE(&dir->subdir_root, sdir, dir);
   1129        1.1       jmc 				dir = sdir;
   1130        1.1       jmc 			}
   1131        1.1       jmc 			else {
   1132        1.1       jmc 				dir = sdir;
   1133        1.1       jmc 				continue;
   1134        1.1       jmc 			}
   1135        1.1       jmc 		} else {
   1136        1.1       jmc 			if (dir->parent)
   1137        1.1       jmc 				TAILQ_REMOVE(&dir->parent->subdir_root, dir,
   1138        1.1       jmc 				    dir);
   1139        1.1       jmc 		}
   1140        1.9     perry 
   1141        1.1       jmc 		while ((data = TAILQ_FIRST(&dir->data_root))) {
   1142        1.1       jmc 			if (data->leafdata) {
   1143        1.1       jmc 				if (data->leafdata->data)
   1144        1.1       jmc 					free(data->leafdata->data, M_DEVBUF);
   1145        1.1       jmc 				free(data->leafdata, M_DEVBUF);
   1146        1.1       jmc 			}
   1147        1.1       jmc 			TAILQ_REMOVE(&dir->data_root, data, data);
   1148        1.1       jmc 			if (data->com.textcnt) {
   1149        1.1       jmc 				for (i = 0; i < data->com.textcnt; i++)
   1150        1.1       jmc 					free(data->com.text[i], M_DEVBUF);
   1151        1.1       jmc 				free(data->com.text, M_DEVBUF);
   1152        1.1       jmc 			}
   1153        1.1       jmc 			free(data, M_DEVBUF);
   1154        1.1       jmc 		}
   1155        1.1       jmc 		sdir = dir;
   1156        1.9     perry 		if (dir->parent)
   1157        1.1       jmc 			dir = dir->parent;
   1158        1.1       jmc 		else
   1159        1.1       jmc 			dir = NULL;
   1160        1.1       jmc 		if (sdir->com.textcnt) {
   1161        1.1       jmc 			for (i = 0; i < sdir->com.textcnt; i++)
   1162        1.1       jmc 				free(sdir->com.text[i], M_DEVBUF);
   1163        1.1       jmc 			free(sdir->com.text, M_DEVBUF);
   1164        1.1       jmc 		}
   1165        1.1       jmc 		free(sdir, M_DEVBUF);
   1166        1.1       jmc 	}
   1167        1.1       jmc 	if (rom->len)
   1168        1.1       jmc 		free(rom->data, M_DEVBUF);
   1169        1.1       jmc 	free(rom, M_DEVBUF);
   1170        1.1       jmc }
   1171        1.1       jmc 
   1172        1.1       jmc /*
   1173        1.1       jmc  * A fairly well published reference implementation of the CRC routine had
   1174        1.1       jmc  * a typo in it and some devices may be using it rather than the correct one
   1175        1.1       jmc  * in calculating their ROM CRC's. To compensate an interface for generating
   1176        1.1       jmc  * either is provided.
   1177        1.1       jmc  *
   1178        1.1       jmc  * len is the number of u_int32_t entries, not bytes.
   1179        1.1       jmc  */
   1180        1.1       jmc 
   1181        1.1       jmc static u_int16_t
   1182        1.1       jmc p1212_calc_crc(u_int32_t crc, u_int32_t *data, int len, int broke)
   1183        1.1       jmc {
   1184        1.1       jmc 	int shift;
   1185        1.1       jmc 	u_int32_t sum;
   1186        1.1       jmc 	int i;
   1187        1.9     perry 
   1188        1.1       jmc 	for (i = 0; i < len; i++) {
   1189        1.1       jmc 		for (shift = 28; shift > 0; shift -= 4) {
   1190        1.1       jmc 			sum = ((crc >> 12) ^ (ntohl(data[i]) >> shift)) &
   1191        1.1       jmc 			    0x0000000f;
   1192        1.1       jmc 			crc = (crc << 4) ^ (sum << 12) ^ (sum << 5) ^ sum;
   1193        1.1       jmc 		}
   1194        1.9     perry 
   1195        1.9     perry 
   1196        1.1       jmc 		/* The broken implementation doesn't do the last shift. */
   1197        1.1       jmc 		if (!broke) {
   1198        1.1       jmc 			sum = ((crc >> 12) ^ ntohl(data[i])) & 0x0000000f;
   1199        1.1       jmc 			crc = (crc << 4) ^ (sum << 12) ^ (sum << 5) ^ sum;
   1200        1.1       jmc 		}
   1201        1.1       jmc 	}
   1202        1.1       jmc 	return (u_int16_t)crc;
   1203        1.1       jmc }
   1204        1.1       jmc 
   1205        1.1       jmc /*
   1206        1.1       jmc  * This is almost identical to the standard autoconf *match idea except it
   1207        1.1       jmc  * can match and attach multiple children in one pass.
   1208        1.1       jmc  */
   1209        1.1       jmc 
   1210  1.10.74.2      yamt device_t *
   1211  1.10.74.2      yamt p1212_match_units(device_t sc, struct p1212_dir *dir,
   1212        1.1       jmc     int (*print)(void *, const char *))
   1213        1.1       jmc {
   1214        1.1       jmc 	struct p1212_dir **udirs;
   1215  1.10.74.2      yamt 	device_t *devret, *dev;
   1216        1.1       jmc 	int numdev;
   1217        1.9     perry 
   1218        1.1       jmc 	/*
   1219        1.1       jmc 	 * Setup typical return val. Always allocate one extra pointer for a
   1220        1.1       jmc 	 * NULL guard end pointer.
   1221        1.1       jmc 	 */
   1222        1.1       jmc 
   1223        1.1       jmc 	numdev = 0;
   1224  1.10.74.2      yamt 	devret = malloc(sizeof(device_t) * 2, M_DEVBUF, M_WAITOK);
   1225        1.1       jmc 	devret[1] = NULL;
   1226        1.1       jmc 
   1227        1.1       jmc 	udirs = (struct p1212_dir **)p1212_find(dir, P1212_KEYTYPE_Directory,
   1228        1.9     perry 	    P1212_KEYVALUE_Unit_Directory,
   1229        1.1       jmc 	    P1212_FIND_SEARCHALL|P1212_FIND_RETURNALL);
   1230        1.9     perry 
   1231        1.1       jmc 	if (udirs) {
   1232        1.3       jmc 		do {
   1233        1.8  drochner 			dev = config_found_ia(sc, "fwnode", udirs, print);
   1234        1.1       jmc 			if (dev && numdev) {
   1235        1.1       jmc 				devret = realloc(devret,
   1236  1.10.74.2      yamt 				    sizeof(device_t) *
   1237        1.1       jmc 				    (numdev + 2), M_DEVBUF, M_WAITOK);
   1238        1.1       jmc 				devret[numdev++] = dev;
   1239        1.1       jmc 				devret[numdev] = NULL;
   1240        1.1       jmc 			} else if (dev) {
   1241        1.1       jmc 				devret[0] = dev;
   1242        1.1       jmc 				numdev++;
   1243        1.1       jmc 			}
   1244        1.3       jmc 			udirs++;
   1245        1.3       jmc 		} while (*udirs);
   1246        1.1       jmc 	}
   1247        1.1       jmc 	if (numdev == 0) {
   1248        1.1       jmc 		free(devret, M_DEVBUF);
   1249        1.1       jmc 		return NULL;
   1250        1.1       jmc 	}
   1251        1.1       jmc 	return devret;
   1252        1.1       jmc }
   1253        1.1       jmc 
   1254        1.9     perry /*
   1255        1.1       jmc  * Make these their own functions as they have slightly complicated rules.
   1256        1.1       jmc  *
   1257        1.1       jmc  * For example:
   1258        1.1       jmc  *
   1259        1.1       jmc  * Under normal circumstances only the 2 extent types can be offset
   1260        1.1       jmc  * types. However some spec's which use p1212 like SBP2 for
   1261        1.9     perry  * firewire/1394 will define a dependent info type as an offset value.
   1262        1.9     perry  * Allow the upper level code to flag this and pass it down during
   1263        1.1       jmc  * parsing. The same thing applies to immediate types.
   1264        1.1       jmc  */
   1265        1.1       jmc 
   1266        1.1       jmc static int
   1267        1.1       jmc p1212_validate_offset(u_int16_t val, u_int32_t mask)
   1268        1.1       jmc {
   1269        1.1       jmc         if ((val == P1212_KEYVALUE_Node_Units_Extent) ||
   1270        1.1       jmc             (val == P1212_KEYVALUE_Node_Memory_Extent) ||
   1271        1.1       jmc             ((mask & P1212_ALLOW_DEPENDENT_INFO_OFFSET_TYPE) &&
   1272        1.9     perry              ((val == P1212_KEYVALUE_Unit_Dependent_Info) ||
   1273        1.9     perry               (val == P1212_KEYVALUE_Node_Dependent_Info) ||
   1274        1.1       jmc               (val == P1212_KEYVALUE_Module_Dependent_Info))))
   1275        1.1       jmc                 return 0;
   1276        1.1       jmc         return 1;
   1277        1.1       jmc }
   1278        1.1       jmc 
   1279        1.9     perry static int
   1280        1.1       jmc p1212_validate_immed(u_int16_t val, u_int32_t mask)
   1281        1.1       jmc {
   1282        1.1       jmc 	switch (val) {
   1283        1.1       jmc 	case P1212_KEYVALUE_Textual_Descriptor:
   1284        1.1       jmc 	case P1212_KEYVALUE_Bus_Dependent_Info:
   1285        1.1       jmc 	case P1212_KEYVALUE_Module_Dependent_Info:
   1286        1.1       jmc 	case P1212_KEYVALUE_Node_Unique_Id:
   1287        1.1       jmc 	case P1212_KEYVALUE_Node_Dependent_Info:
   1288        1.1       jmc 	case P1212_KEYVALUE_Unit_Directory:
   1289        1.1       jmc 	case P1212_KEYVALUE_Unit_Dependent_Info:
   1290        1.1       jmc 	case P1212_KEYVALUE_Unit_Location:
   1291        1.1       jmc 		if ((mask & P1212_ALLOW_DEPENDENT_INFO_IMMED_TYPE) &&
   1292        1.1       jmc 		    ((val == P1212_KEYVALUE_Module_Dependent_Info) ||
   1293        1.1       jmc 		     (val == P1212_KEYVALUE_Node_Dependent_Info) ||
   1294        1.1       jmc 		     (val == P1212_KEYVALUE_Unit_Dependent_Info)))
   1295        1.1       jmc 			break;
   1296        1.1       jmc 		return 1;
   1297        1.1       jmc 		break;
   1298        1.1       jmc 	default:
   1299        1.1       jmc 		break;
   1300        1.1       jmc 	}
   1301        1.1       jmc 	return 0;
   1302        1.1       jmc }
   1303        1.1       jmc 
   1304        1.1       jmc static int
   1305        1.1       jmc p1212_validate_leaf(u_int16_t val, u_int32_t mask)
   1306        1.1       jmc {
   1307        1.1       jmc 	switch(val) {
   1308        1.1       jmc 	case P1212_KEYVALUE_Textual_Descriptor:
   1309        1.1       jmc 	case P1212_KEYVALUE_Bus_Dependent_Info:
   1310        1.1       jmc 	case P1212_KEYVALUE_Module_Dependent_Info:
   1311        1.1       jmc 	case P1212_KEYVALUE_Node_Unique_Id:
   1312        1.1       jmc 	case P1212_KEYVALUE_Node_Dependent_Info:
   1313        1.1       jmc 	case P1212_KEYVALUE_Unit_Dependent_Info:
   1314        1.1       jmc 	case P1212_KEYVALUE_Unit_Location:
   1315        1.1       jmc 		break;
   1316        1.1       jmc 	default:
   1317        1.1       jmc 		return 1;
   1318        1.1       jmc 		break;
   1319        1.1       jmc 	}
   1320        1.1       jmc 	return 0;
   1321        1.1       jmc }
   1322        1.1       jmc 
   1323        1.1       jmc static int
   1324        1.1       jmc p1212_validate_dir(u_int16_t val, u_int32_t mask)
   1325        1.1       jmc {
   1326        1.1       jmc 	switch(val) {
   1327        1.1       jmc 	case P1212_KEYVALUE_Textual_Descriptor:
   1328        1.1       jmc 	case P1212_KEYVALUE_Bus_Dependent_Info:
   1329        1.1       jmc 	case P1212_KEYVALUE_Module_Dependent_Info:
   1330        1.1       jmc 	case P1212_KEYVALUE_Node_Dependent_Info:
   1331        1.1       jmc 	case P1212_KEYVALUE_Unit_Directory:
   1332        1.1       jmc 	case P1212_KEYVALUE_Unit_Dependent_Info:
   1333        1.1       jmc 		break;
   1334        1.1       jmc 	default:
   1335        1.2       jmc 		if ((mask & P1212_ALLOW_VENDOR_DIRECTORY_TYPE) &&
   1336        1.2       jmc 		    (val == P1212_KEYVALUE_Module_Vendor_Id))
   1337        1.2       jmc 			break;
   1338        1.1       jmc 		return 1;
   1339        1.1       jmc 		break;
   1340        1.1       jmc 	}
   1341        1.1       jmc 	return 0;
   1342        1.1       jmc }
   1343