xref: /openbmc/linux/drivers/pnp/pnpbios/rsparser.c (revision a1e58bbd)
1 /*
2  * rsparser.c - parses and encodes pnpbios resource data streams
3  */
4 
5 #include <linux/ctype.h>
6 #include <linux/pnp.h>
7 #include <linux/pnpbios.h>
8 #include <linux/string.h>
9 #include <linux/slab.h>
10 
11 #ifdef CONFIG_PCI
12 #include <linux/pci.h>
13 #else
14 inline void pcibios_penalize_isa_irq(int irq, int active)
15 {
16 }
17 #endif				/* CONFIG_PCI */
18 
19 #include "pnpbios.h"
20 
21 /* standard resource tags */
22 #define SMALL_TAG_PNPVERNO		0x01
23 #define SMALL_TAG_LOGDEVID		0x02
24 #define SMALL_TAG_COMPATDEVID		0x03
25 #define SMALL_TAG_IRQ			0x04
26 #define SMALL_TAG_DMA			0x05
27 #define SMALL_TAG_STARTDEP		0x06
28 #define SMALL_TAG_ENDDEP		0x07
29 #define SMALL_TAG_PORT			0x08
30 #define SMALL_TAG_FIXEDPORT		0x09
31 #define SMALL_TAG_VENDOR		0x0e
32 #define SMALL_TAG_END			0x0f
33 #define LARGE_TAG			0x80
34 #define LARGE_TAG_MEM			0x81
35 #define LARGE_TAG_ANSISTR		0x82
36 #define LARGE_TAG_UNICODESTR		0x83
37 #define LARGE_TAG_VENDOR		0x84
38 #define LARGE_TAG_MEM32			0x85
39 #define LARGE_TAG_FIXEDMEM32		0x86
40 
41 /*
42  * Resource Data Stream Format:
43  *
44  * Allocated Resources (required)
45  * end tag ->
46  * Resource Configuration Options (optional)
47  * end tag ->
48  * Compitable Device IDs (optional)
49  * final end tag ->
50  */
51 
52 /*
53  * Allocated Resources
54  */
55 
56 static void pnpbios_parse_allocated_irqresource(struct pnp_resource_table *res,
57 						int irq)
58 {
59 	int i = 0;
60 
61 	while (!(res->irq_resource[i].flags & IORESOURCE_UNSET)
62 	       && i < PNP_MAX_IRQ)
63 		i++;
64 	if (i < PNP_MAX_IRQ) {
65 		res->irq_resource[i].flags = IORESOURCE_IRQ;	// Also clears _UNSET flag
66 		if (irq == -1) {
67 			res->irq_resource[i].flags |= IORESOURCE_DISABLED;
68 			return;
69 		}
70 		res->irq_resource[i].start =
71 		    res->irq_resource[i].end = (unsigned long)irq;
72 		pcibios_penalize_isa_irq(irq, 1);
73 	}
74 }
75 
76 static void pnpbios_parse_allocated_dmaresource(struct pnp_resource_table *res,
77 						int dma)
78 {
79 	int i = 0;
80 
81 	while (i < PNP_MAX_DMA &&
82 	       !(res->dma_resource[i].flags & IORESOURCE_UNSET))
83 		i++;
84 	if (i < PNP_MAX_DMA) {
85 		res->dma_resource[i].flags = IORESOURCE_DMA;	// Also clears _UNSET flag
86 		if (dma == -1) {
87 			res->dma_resource[i].flags |= IORESOURCE_DISABLED;
88 			return;
89 		}
90 		res->dma_resource[i].start =
91 		    res->dma_resource[i].end = (unsigned long)dma;
92 	}
93 }
94 
95 static void pnpbios_parse_allocated_ioresource(struct pnp_resource_table *res,
96 					       int io, int len)
97 {
98 	int i = 0;
99 
100 	while (!(res->port_resource[i].flags & IORESOURCE_UNSET)
101 	       && i < PNP_MAX_PORT)
102 		i++;
103 	if (i < PNP_MAX_PORT) {
104 		res->port_resource[i].flags = IORESOURCE_IO;	// Also clears _UNSET flag
105 		if (len <= 0 || (io + len - 1) >= 0x10003) {
106 			res->port_resource[i].flags |= IORESOURCE_DISABLED;
107 			return;
108 		}
109 		res->port_resource[i].start = (unsigned long)io;
110 		res->port_resource[i].end = (unsigned long)(io + len - 1);
111 	}
112 }
113 
114 static void pnpbios_parse_allocated_memresource(struct pnp_resource_table *res,
115 						int mem, int len)
116 {
117 	int i = 0;
118 
119 	while (!(res->mem_resource[i].flags & IORESOURCE_UNSET)
120 	       && i < PNP_MAX_MEM)
121 		i++;
122 	if (i < PNP_MAX_MEM) {
123 		res->mem_resource[i].flags = IORESOURCE_MEM;	// Also clears _UNSET flag
124 		if (len <= 0) {
125 			res->mem_resource[i].flags |= IORESOURCE_DISABLED;
126 			return;
127 		}
128 		res->mem_resource[i].start = (unsigned long)mem;
129 		res->mem_resource[i].end = (unsigned long)(mem + len - 1);
130 	}
131 }
132 
133 static unsigned char *pnpbios_parse_allocated_resource_data(unsigned char *p,
134 							    unsigned char *end,
135 							    struct
136 							    pnp_resource_table
137 							    *res)
138 {
139 	unsigned int len, tag;
140 	int io, size, mask, i;
141 
142 	if (!p)
143 		return NULL;
144 
145 	/* Blank the resource table values */
146 	pnp_init_resource_table(res);
147 
148 	while ((char *)p < (char *)end) {
149 
150 		/* determine the type of tag */
151 		if (p[0] & LARGE_TAG) {	/* large tag */
152 			len = (p[2] << 8) | p[1];
153 			tag = p[0];
154 		} else {	/* small tag */
155 			len = p[0] & 0x07;
156 			tag = ((p[0] >> 3) & 0x0f);
157 		}
158 
159 		switch (tag) {
160 
161 		case LARGE_TAG_MEM:
162 			if (len != 9)
163 				goto len_err;
164 			io = *(short *)&p[4];
165 			size = *(short *)&p[10];
166 			pnpbios_parse_allocated_memresource(res, io, size);
167 			break;
168 
169 		case LARGE_TAG_ANSISTR:
170 			/* ignore this for now */
171 			break;
172 
173 		case LARGE_TAG_VENDOR:
174 			/* do nothing */
175 			break;
176 
177 		case LARGE_TAG_MEM32:
178 			if (len != 17)
179 				goto len_err;
180 			io = *(int *)&p[4];
181 			size = *(int *)&p[16];
182 			pnpbios_parse_allocated_memresource(res, io, size);
183 			break;
184 
185 		case LARGE_TAG_FIXEDMEM32:
186 			if (len != 9)
187 				goto len_err;
188 			io = *(int *)&p[4];
189 			size = *(int *)&p[8];
190 			pnpbios_parse_allocated_memresource(res, io, size);
191 			break;
192 
193 		case SMALL_TAG_IRQ:
194 			if (len < 2 || len > 3)
195 				goto len_err;
196 			io = -1;
197 			mask = p[1] + p[2] * 256;
198 			for (i = 0; i < 16; i++, mask = mask >> 1)
199 				if (mask & 0x01)
200 					io = i;
201 			pnpbios_parse_allocated_irqresource(res, io);
202 			break;
203 
204 		case SMALL_TAG_DMA:
205 			if (len != 2)
206 				goto len_err;
207 			io = -1;
208 			mask = p[1];
209 			for (i = 0; i < 8; i++, mask = mask >> 1)
210 				if (mask & 0x01)
211 					io = i;
212 			pnpbios_parse_allocated_dmaresource(res, io);
213 			break;
214 
215 		case SMALL_TAG_PORT:
216 			if (len != 7)
217 				goto len_err;
218 			io = p[2] + p[3] * 256;
219 			size = p[7];
220 			pnpbios_parse_allocated_ioresource(res, io, size);
221 			break;
222 
223 		case SMALL_TAG_VENDOR:
224 			/* do nothing */
225 			break;
226 
227 		case SMALL_TAG_FIXEDPORT:
228 			if (len != 3)
229 				goto len_err;
230 			io = p[1] + p[2] * 256;
231 			size = p[3];
232 			pnpbios_parse_allocated_ioresource(res, io, size);
233 			break;
234 
235 		case SMALL_TAG_END:
236 			p = p + 2;
237 			return (unsigned char *)p;
238 			break;
239 
240 		default:	/* an unkown tag */
241 len_err:
242 			printk(KERN_ERR
243 			       "PnPBIOS: Unknown tag '0x%x', length '%d'.\n",
244 			       tag, len);
245 			break;
246 		}
247 
248 		/* continue to the next tag */
249 		if (p[0] & LARGE_TAG)
250 			p += len + 3;
251 		else
252 			p += len + 1;
253 	}
254 
255 	printk(KERN_ERR
256 	       "PnPBIOS: Resource structure does not contain an end tag.\n");
257 
258 	return NULL;
259 }
260 
261 /*
262  * Resource Configuration Options
263  */
264 
265 static __init void pnpbios_parse_mem_option(unsigned char *p, int size,
266 					    struct pnp_option *option)
267 {
268 	struct pnp_mem *mem;
269 
270 	mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL);
271 	if (!mem)
272 		return;
273 	mem->min = ((p[5] << 8) | p[4]) << 8;
274 	mem->max = ((p[7] << 8) | p[6]) << 8;
275 	mem->align = (p[9] << 8) | p[8];
276 	mem->size = ((p[11] << 8) | p[10]) << 8;
277 	mem->flags = p[3];
278 	pnp_register_mem_resource(option, mem);
279 }
280 
281 static __init void pnpbios_parse_mem32_option(unsigned char *p, int size,
282 					      struct pnp_option *option)
283 {
284 	struct pnp_mem *mem;
285 
286 	mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL);
287 	if (!mem)
288 		return;
289 	mem->min = (p[7] << 24) | (p[6] << 16) | (p[5] << 8) | p[4];
290 	mem->max = (p[11] << 24) | (p[10] << 16) | (p[9] << 8) | p[8];
291 	mem->align = (p[15] << 24) | (p[14] << 16) | (p[13] << 8) | p[12];
292 	mem->size = (p[19] << 24) | (p[18] << 16) | (p[17] << 8) | p[16];
293 	mem->flags = p[3];
294 	pnp_register_mem_resource(option, mem);
295 }
296 
297 static __init void pnpbios_parse_fixed_mem32_option(unsigned char *p, int size,
298 						    struct pnp_option *option)
299 {
300 	struct pnp_mem *mem;
301 
302 	mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL);
303 	if (!mem)
304 		return;
305 	mem->min = mem->max = (p[7] << 24) | (p[6] << 16) | (p[5] << 8) | p[4];
306 	mem->size = (p[11] << 24) | (p[10] << 16) | (p[9] << 8) | p[8];
307 	mem->align = 0;
308 	mem->flags = p[3];
309 	pnp_register_mem_resource(option, mem);
310 }
311 
312 static __init void pnpbios_parse_irq_option(unsigned char *p, int size,
313 				     struct pnp_option *option)
314 {
315 	struct pnp_irq *irq;
316 	unsigned long bits;
317 
318 	irq = kzalloc(sizeof(struct pnp_irq), GFP_KERNEL);
319 	if (!irq)
320 		return;
321 	bits = (p[2] << 8) | p[1];
322 	bitmap_copy(irq->map, &bits, 16);
323 	if (size > 2)
324 		irq->flags = p[3];
325 	else
326 		irq->flags = IORESOURCE_IRQ_HIGHEDGE;
327 	pnp_register_irq_resource(option, irq);
328 }
329 
330 static __init void pnpbios_parse_dma_option(unsigned char *p, int size,
331 				     struct pnp_option *option)
332 {
333 	struct pnp_dma *dma;
334 
335 	dma = kzalloc(sizeof(struct pnp_dma), GFP_KERNEL);
336 	if (!dma)
337 		return;
338 	dma->map = p[1];
339 	dma->flags = p[2];
340 	pnp_register_dma_resource(option, dma);
341 }
342 
343 static __init void pnpbios_parse_port_option(unsigned char *p, int size,
344 					     struct pnp_option *option)
345 {
346 	struct pnp_port *port;
347 
348 	port = kzalloc(sizeof(struct pnp_port), GFP_KERNEL);
349 	if (!port)
350 		return;
351 	port->min = (p[3] << 8) | p[2];
352 	port->max = (p[5] << 8) | p[4];
353 	port->align = p[6];
354 	port->size = p[7];
355 	port->flags = p[1] ? PNP_PORT_FLAG_16BITADDR : 0;
356 	pnp_register_port_resource(option, port);
357 }
358 
359 static __init void pnpbios_parse_fixed_port_option(unsigned char *p, int size,
360 						   struct pnp_option *option)
361 {
362 	struct pnp_port *port;
363 
364 	port = kzalloc(sizeof(struct pnp_port), GFP_KERNEL);
365 	if (!port)
366 		return;
367 	port->min = port->max = (p[2] << 8) | p[1];
368 	port->size = p[3];
369 	port->align = 0;
370 	port->flags = PNP_PORT_FLAG_FIXED;
371 	pnp_register_port_resource(option, port);
372 }
373 
374 static __init unsigned char *
375 pnpbios_parse_resource_option_data(unsigned char *p, unsigned char *end,
376 					struct pnp_dev *dev)
377 {
378 	unsigned int len, tag;
379 	int priority = 0;
380 	struct pnp_option *option, *option_independent;
381 
382 	if (!p)
383 		return NULL;
384 
385 	option_independent = option = pnp_register_independent_option(dev);
386 	if (!option)
387 		return NULL;
388 
389 	while ((char *)p < (char *)end) {
390 
391 		/* determine the type of tag */
392 		if (p[0] & LARGE_TAG) {	/* large tag */
393 			len = (p[2] << 8) | p[1];
394 			tag = p[0];
395 		} else {	/* small tag */
396 			len = p[0] & 0x07;
397 			tag = ((p[0] >> 3) & 0x0f);
398 		}
399 
400 		switch (tag) {
401 
402 		case LARGE_TAG_MEM:
403 			if (len != 9)
404 				goto len_err;
405 			pnpbios_parse_mem_option(p, len, option);
406 			break;
407 
408 		case LARGE_TAG_MEM32:
409 			if (len != 17)
410 				goto len_err;
411 			pnpbios_parse_mem32_option(p, len, option);
412 			break;
413 
414 		case LARGE_TAG_FIXEDMEM32:
415 			if (len != 9)
416 				goto len_err;
417 			pnpbios_parse_fixed_mem32_option(p, len, option);
418 			break;
419 
420 		case SMALL_TAG_IRQ:
421 			if (len < 2 || len > 3)
422 				goto len_err;
423 			pnpbios_parse_irq_option(p, len, option);
424 			break;
425 
426 		case SMALL_TAG_DMA:
427 			if (len != 2)
428 				goto len_err;
429 			pnpbios_parse_dma_option(p, len, option);
430 			break;
431 
432 		case SMALL_TAG_PORT:
433 			if (len != 7)
434 				goto len_err;
435 			pnpbios_parse_port_option(p, len, option);
436 			break;
437 
438 		case SMALL_TAG_VENDOR:
439 			/* do nothing */
440 			break;
441 
442 		case SMALL_TAG_FIXEDPORT:
443 			if (len != 3)
444 				goto len_err;
445 			pnpbios_parse_fixed_port_option(p, len, option);
446 			break;
447 
448 		case SMALL_TAG_STARTDEP:
449 			if (len > 1)
450 				goto len_err;
451 			priority = 0x100 | PNP_RES_PRIORITY_ACCEPTABLE;
452 			if (len > 0)
453 				priority = 0x100 | p[1];
454 			option = pnp_register_dependent_option(dev, priority);
455 			if (!option)
456 				return NULL;
457 			break;
458 
459 		case SMALL_TAG_ENDDEP:
460 			if (len != 0)
461 				goto len_err;
462 			if (option_independent == option)
463 				printk(KERN_WARNING
464 				       "PnPBIOS: Missing SMALL_TAG_STARTDEP tag\n");
465 			option = option_independent;
466 			break;
467 
468 		case SMALL_TAG_END:
469 			return p + 2;
470 
471 		default:	/* an unkown tag */
472 len_err:
473 			printk(KERN_ERR
474 			       "PnPBIOS: Unknown tag '0x%x', length '%d'.\n",
475 			       tag, len);
476 			break;
477 		}
478 
479 		/* continue to the next tag */
480 		if (p[0] & LARGE_TAG)
481 			p += len + 3;
482 		else
483 			p += len + 1;
484 	}
485 
486 	printk(KERN_ERR
487 	       "PnPBIOS: Resource structure does not contain an end tag.\n");
488 
489 	return NULL;
490 }
491 
492 /*
493  * Compatible Device IDs
494  */
495 
496 #define HEX(id,a) hex[((id)>>a) & 15]
497 #define CHAR(id,a) (0x40 + (((id)>>a) & 31))
498 
499 void pnpid32_to_pnpid(u32 id, char *str)
500 {
501 	const char *hex = "0123456789abcdef";
502 
503 	id = be32_to_cpu(id);
504 	str[0] = CHAR(id, 26);
505 	str[1] = CHAR(id, 21);
506 	str[2] = CHAR(id, 16);
507 	str[3] = HEX(id, 12);
508 	str[4] = HEX(id, 8);
509 	str[5] = HEX(id, 4);
510 	str[6] = HEX(id, 0);
511 	str[7] = '\0';
512 }
513 
514 #undef CHAR
515 #undef HEX
516 
517 static unsigned char *pnpbios_parse_compatible_ids(unsigned char *p,
518 						   unsigned char *end,
519 						   struct pnp_dev *dev)
520 {
521 	int len, tag;
522 	char id[8];
523 	struct pnp_id *dev_id;
524 
525 	if (!p)
526 		return NULL;
527 
528 	while ((char *)p < (char *)end) {
529 
530 		/* determine the type of tag */
531 		if (p[0] & LARGE_TAG) {	/* large tag */
532 			len = (p[2] << 8) | p[1];
533 			tag = p[0];
534 		} else {	/* small tag */
535 			len = p[0] & 0x07;
536 			tag = ((p[0] >> 3) & 0x0f);
537 		}
538 
539 		switch (tag) {
540 
541 		case LARGE_TAG_ANSISTR:
542 			strncpy(dev->name, p + 3,
543 				len >= PNP_NAME_LEN ? PNP_NAME_LEN - 2 : len);
544 			dev->name[len >=
545 				  PNP_NAME_LEN ? PNP_NAME_LEN - 1 : len] = '\0';
546 			break;
547 
548 		case SMALL_TAG_COMPATDEVID:	/* compatible ID */
549 			if (len != 4)
550 				goto len_err;
551 			dev_id = kzalloc(sizeof(struct pnp_id), GFP_KERNEL);
552 			if (!dev_id)
553 				return NULL;
554 			pnpid32_to_pnpid(p[1] | p[2] << 8 | p[3] << 16 | p[4] <<
555 					 24, id);
556 			memcpy(&dev_id->id, id, 7);
557 			pnp_add_id(dev_id, dev);
558 			break;
559 
560 		case SMALL_TAG_END:
561 			p = p + 2;
562 			return (unsigned char *)p;
563 			break;
564 
565 		default:	/* an unkown tag */
566 len_err:
567 			printk(KERN_ERR
568 			       "PnPBIOS: Unknown tag '0x%x', length '%d'.\n",
569 			       tag, len);
570 			break;
571 		}
572 
573 		/* continue to the next tag */
574 		if (p[0] & LARGE_TAG)
575 			p += len + 3;
576 		else
577 			p += len + 1;
578 	}
579 
580 	printk(KERN_ERR
581 	       "PnPBIOS: Resource structure does not contain an end tag.\n");
582 
583 	return NULL;
584 }
585 
586 /*
587  * Allocated Resource Encoding
588  */
589 
590 static void pnpbios_encode_mem(unsigned char *p, struct resource *res)
591 {
592 	unsigned long base = res->start;
593 	unsigned long len = res->end - res->start + 1;
594 
595 	p[4] = (base >> 8) & 0xff;
596 	p[5] = ((base >> 8) >> 8) & 0xff;
597 	p[6] = (base >> 8) & 0xff;
598 	p[7] = ((base >> 8) >> 8) & 0xff;
599 	p[10] = (len >> 8) & 0xff;
600 	p[11] = ((len >> 8) >> 8) & 0xff;
601 }
602 
603 static void pnpbios_encode_mem32(unsigned char *p, struct resource *res)
604 {
605 	unsigned long base = res->start;
606 	unsigned long len = res->end - res->start + 1;
607 
608 	p[4] = base & 0xff;
609 	p[5] = (base >> 8) & 0xff;
610 	p[6] = (base >> 16) & 0xff;
611 	p[7] = (base >> 24) & 0xff;
612 	p[8] = base & 0xff;
613 	p[9] = (base >> 8) & 0xff;
614 	p[10] = (base >> 16) & 0xff;
615 	p[11] = (base >> 24) & 0xff;
616 	p[16] = len & 0xff;
617 	p[17] = (len >> 8) & 0xff;
618 	p[18] = (len >> 16) & 0xff;
619 	p[19] = (len >> 24) & 0xff;
620 }
621 
622 static void pnpbios_encode_fixed_mem32(unsigned char *p, struct resource *res)
623 {
624 	unsigned long base = res->start;
625 	unsigned long len = res->end - res->start + 1;
626 
627 	p[4] = base & 0xff;
628 	p[5] = (base >> 8) & 0xff;
629 	p[6] = (base >> 16) & 0xff;
630 	p[7] = (base >> 24) & 0xff;
631 	p[8] = len & 0xff;
632 	p[9] = (len >> 8) & 0xff;
633 	p[10] = (len >> 16) & 0xff;
634 	p[11] = (len >> 24) & 0xff;
635 }
636 
637 static void pnpbios_encode_irq(unsigned char *p, struct resource *res)
638 {
639 	unsigned long map = 0;
640 
641 	map = 1 << res->start;
642 	p[1] = map & 0xff;
643 	p[2] = (map >> 8) & 0xff;
644 }
645 
646 static void pnpbios_encode_dma(unsigned char *p, struct resource *res)
647 {
648 	unsigned long map = 0;
649 
650 	map = 1 << res->start;
651 	p[1] = map & 0xff;
652 }
653 
654 static void pnpbios_encode_port(unsigned char *p, struct resource *res)
655 {
656 	unsigned long base = res->start;
657 	unsigned long len = res->end - res->start + 1;
658 
659 	p[2] = base & 0xff;
660 	p[3] = (base >> 8) & 0xff;
661 	p[4] = base & 0xff;
662 	p[5] = (base >> 8) & 0xff;
663 	p[7] = len & 0xff;
664 }
665 
666 static void pnpbios_encode_fixed_port(unsigned char *p, struct resource *res)
667 {
668 	unsigned long base = res->start;
669 	unsigned long len = res->end - res->start + 1;
670 
671 	p[1] = base & 0xff;
672 	p[2] = (base >> 8) & 0xff;
673 	p[3] = len & 0xff;
674 }
675 
676 static unsigned char *pnpbios_encode_allocated_resource_data(unsigned char *p,
677 							     unsigned char *end,
678 							     struct
679 							     pnp_resource_table
680 							     *res)
681 {
682 	unsigned int len, tag;
683 	int port = 0, irq = 0, dma = 0, mem = 0;
684 
685 	if (!p)
686 		return NULL;
687 
688 	while ((char *)p < (char *)end) {
689 
690 		/* determine the type of tag */
691 		if (p[0] & LARGE_TAG) {	/* large tag */
692 			len = (p[2] << 8) | p[1];
693 			tag = p[0];
694 		} else {	/* small tag */
695 			len = p[0] & 0x07;
696 			tag = ((p[0] >> 3) & 0x0f);
697 		}
698 
699 		switch (tag) {
700 
701 		case LARGE_TAG_MEM:
702 			if (len != 9)
703 				goto len_err;
704 			pnpbios_encode_mem(p, &res->mem_resource[mem]);
705 			mem++;
706 			break;
707 
708 		case LARGE_TAG_MEM32:
709 			if (len != 17)
710 				goto len_err;
711 			pnpbios_encode_mem32(p, &res->mem_resource[mem]);
712 			mem++;
713 			break;
714 
715 		case LARGE_TAG_FIXEDMEM32:
716 			if (len != 9)
717 				goto len_err;
718 			pnpbios_encode_fixed_mem32(p, &res->mem_resource[mem]);
719 			mem++;
720 			break;
721 
722 		case SMALL_TAG_IRQ:
723 			if (len < 2 || len > 3)
724 				goto len_err;
725 			pnpbios_encode_irq(p, &res->irq_resource[irq]);
726 			irq++;
727 			break;
728 
729 		case SMALL_TAG_DMA:
730 			if (len != 2)
731 				goto len_err;
732 			pnpbios_encode_dma(p, &res->dma_resource[dma]);
733 			dma++;
734 			break;
735 
736 		case SMALL_TAG_PORT:
737 			if (len != 7)
738 				goto len_err;
739 			pnpbios_encode_port(p, &res->port_resource[port]);
740 			port++;
741 			break;
742 
743 		case SMALL_TAG_VENDOR:
744 			/* do nothing */
745 			break;
746 
747 		case SMALL_TAG_FIXEDPORT:
748 			if (len != 3)
749 				goto len_err;
750 			pnpbios_encode_fixed_port(p, &res->port_resource[port]);
751 			port++;
752 			break;
753 
754 		case SMALL_TAG_END:
755 			p = p + 2;
756 			return (unsigned char *)p;
757 			break;
758 
759 		default:	/* an unkown tag */
760 len_err:
761 			printk(KERN_ERR
762 			       "PnPBIOS: Unknown tag '0x%x', length '%d'.\n",
763 			       tag, len);
764 			break;
765 		}
766 
767 		/* continue to the next tag */
768 		if (p[0] & LARGE_TAG)
769 			p += len + 3;
770 		else
771 			p += len + 1;
772 	}
773 
774 	printk(KERN_ERR
775 	       "PnPBIOS: Resource structure does not contain an end tag.\n");
776 
777 	return NULL;
778 }
779 
780 /*
781  * Core Parsing Functions
782  */
783 
784 int __init pnpbios_parse_data_stream(struct pnp_dev *dev,
785 					struct pnp_bios_node *node)
786 {
787 	unsigned char *p = (char *)node->data;
788 	unsigned char *end = (char *)(node->data + node->size);
789 
790 	p = pnpbios_parse_allocated_resource_data(p, end, &dev->res);
791 	if (!p)
792 		return -EIO;
793 	p = pnpbios_parse_resource_option_data(p, end, dev);
794 	if (!p)
795 		return -EIO;
796 	p = pnpbios_parse_compatible_ids(p, end, dev);
797 	if (!p)
798 		return -EIO;
799 	return 0;
800 }
801 
802 int pnpbios_read_resources_from_node(struct pnp_resource_table *res,
803 				     struct pnp_bios_node *node)
804 {
805 	unsigned char *p = (char *)node->data;
806 	unsigned char *end = (char *)(node->data + node->size);
807 
808 	p = pnpbios_parse_allocated_resource_data(p, end, res);
809 	if (!p)
810 		return -EIO;
811 	return 0;
812 }
813 
814 int pnpbios_write_resources_to_node(struct pnp_resource_table *res,
815 				    struct pnp_bios_node *node)
816 {
817 	unsigned char *p = (char *)node->data;
818 	unsigned char *end = (char *)(node->data + node->size);
819 
820 	p = pnpbios_encode_allocated_resource_data(p, end, res);
821 	if (!p)
822 		return -EIO;
823 	return 0;
824 }
825