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