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