162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * rsparser.c - parses and encodes pnpbios resource data streams 462306a36Sopenharmony_ci */ 562306a36Sopenharmony_ci 662306a36Sopenharmony_ci#include <linux/ctype.h> 762306a36Sopenharmony_ci#include <linux/pnp.h> 862306a36Sopenharmony_ci#include <linux/string.h> 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#ifdef CONFIG_PCI 1162306a36Sopenharmony_ci#include <linux/pci.h> 1262306a36Sopenharmony_ci#else 1362306a36Sopenharmony_ciinline void pcibios_penalize_isa_irq(int irq, int active) 1462306a36Sopenharmony_ci{ 1562306a36Sopenharmony_ci} 1662306a36Sopenharmony_ci#endif /* CONFIG_PCI */ 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ci#include "../base.h" 1962306a36Sopenharmony_ci#include "pnpbios.h" 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_ci/* standard resource tags */ 2262306a36Sopenharmony_ci#define SMALL_TAG_PNPVERNO 0x01 2362306a36Sopenharmony_ci#define SMALL_TAG_LOGDEVID 0x02 2462306a36Sopenharmony_ci#define SMALL_TAG_COMPATDEVID 0x03 2562306a36Sopenharmony_ci#define SMALL_TAG_IRQ 0x04 2662306a36Sopenharmony_ci#define SMALL_TAG_DMA 0x05 2762306a36Sopenharmony_ci#define SMALL_TAG_STARTDEP 0x06 2862306a36Sopenharmony_ci#define SMALL_TAG_ENDDEP 0x07 2962306a36Sopenharmony_ci#define SMALL_TAG_PORT 0x08 3062306a36Sopenharmony_ci#define SMALL_TAG_FIXEDPORT 0x09 3162306a36Sopenharmony_ci#define SMALL_TAG_VENDOR 0x0e 3262306a36Sopenharmony_ci#define SMALL_TAG_END 0x0f 3362306a36Sopenharmony_ci#define LARGE_TAG 0x80 3462306a36Sopenharmony_ci#define LARGE_TAG_MEM 0x81 3562306a36Sopenharmony_ci#define LARGE_TAG_ANSISTR 0x82 3662306a36Sopenharmony_ci#define LARGE_TAG_UNICODESTR 0x83 3762306a36Sopenharmony_ci#define LARGE_TAG_VENDOR 0x84 3862306a36Sopenharmony_ci#define LARGE_TAG_MEM32 0x85 3962306a36Sopenharmony_ci#define LARGE_TAG_FIXEDMEM32 0x86 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_ci/* 4262306a36Sopenharmony_ci * Resource Data Stream Format: 4362306a36Sopenharmony_ci * 4462306a36Sopenharmony_ci * Allocated Resources (required) 4562306a36Sopenharmony_ci * end tag -> 4662306a36Sopenharmony_ci * Resource Configuration Options (optional) 4762306a36Sopenharmony_ci * end tag -> 4862306a36Sopenharmony_ci * Compitable Device IDs (optional) 4962306a36Sopenharmony_ci * final end tag -> 5062306a36Sopenharmony_ci */ 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ci/* 5362306a36Sopenharmony_ci * Allocated Resources 5462306a36Sopenharmony_ci */ 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_cistatic void pnpbios_parse_allocated_ioresource(struct pnp_dev *dev, 5762306a36Sopenharmony_ci int start, int len) 5862306a36Sopenharmony_ci{ 5962306a36Sopenharmony_ci int flags = 0; 6062306a36Sopenharmony_ci int end = start + len - 1; 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci if (len <= 0 || end >= 0x10003) 6362306a36Sopenharmony_ci flags |= IORESOURCE_DISABLED; 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ci pnp_add_io_resource(dev, start, end, flags); 6662306a36Sopenharmony_ci} 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_cistatic void pnpbios_parse_allocated_memresource(struct pnp_dev *dev, 6962306a36Sopenharmony_ci int start, int len) 7062306a36Sopenharmony_ci{ 7162306a36Sopenharmony_ci int flags = 0; 7262306a36Sopenharmony_ci int end = start + len - 1; 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_ci if (len <= 0) 7562306a36Sopenharmony_ci flags |= IORESOURCE_DISABLED; 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ci pnp_add_mem_resource(dev, start, end, flags); 7862306a36Sopenharmony_ci} 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_cistatic unsigned char *pnpbios_parse_allocated_resource_data(struct pnp_dev *dev, 8162306a36Sopenharmony_ci unsigned char *p, 8262306a36Sopenharmony_ci unsigned char *end) 8362306a36Sopenharmony_ci{ 8462306a36Sopenharmony_ci unsigned int len, tag; 8562306a36Sopenharmony_ci int io, size, mask, i, flags; 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_ci if (!p) 8862306a36Sopenharmony_ci return NULL; 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_ci pnp_dbg(&dev->dev, "parse allocated resources\n"); 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_ci pnp_init_resources(dev); 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_ci while ((char *)p < (char *)end) { 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_ci /* determine the type of tag */ 9762306a36Sopenharmony_ci if (p[0] & LARGE_TAG) { /* large tag */ 9862306a36Sopenharmony_ci len = (p[2] << 8) | p[1]; 9962306a36Sopenharmony_ci tag = p[0]; 10062306a36Sopenharmony_ci } else { /* small tag */ 10162306a36Sopenharmony_ci len = p[0] & 0x07; 10262306a36Sopenharmony_ci tag = ((p[0] >> 3) & 0x0f); 10362306a36Sopenharmony_ci } 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_ci switch (tag) { 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ci case LARGE_TAG_MEM: 10862306a36Sopenharmony_ci if (len != 9) 10962306a36Sopenharmony_ci goto len_err; 11062306a36Sopenharmony_ci io = *(short *)&p[4]; 11162306a36Sopenharmony_ci size = *(short *)&p[10]; 11262306a36Sopenharmony_ci pnpbios_parse_allocated_memresource(dev, io, size); 11362306a36Sopenharmony_ci break; 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_ci case LARGE_TAG_ANSISTR: 11662306a36Sopenharmony_ci /* ignore this for now */ 11762306a36Sopenharmony_ci break; 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_ci case LARGE_TAG_VENDOR: 12062306a36Sopenharmony_ci /* do nothing */ 12162306a36Sopenharmony_ci break; 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_ci case LARGE_TAG_MEM32: 12462306a36Sopenharmony_ci if (len != 17) 12562306a36Sopenharmony_ci goto len_err; 12662306a36Sopenharmony_ci io = *(int *)&p[4]; 12762306a36Sopenharmony_ci size = *(int *)&p[16]; 12862306a36Sopenharmony_ci pnpbios_parse_allocated_memresource(dev, io, size); 12962306a36Sopenharmony_ci break; 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_ci case LARGE_TAG_FIXEDMEM32: 13262306a36Sopenharmony_ci if (len != 9) 13362306a36Sopenharmony_ci goto len_err; 13462306a36Sopenharmony_ci io = *(int *)&p[4]; 13562306a36Sopenharmony_ci size = *(int *)&p[8]; 13662306a36Sopenharmony_ci pnpbios_parse_allocated_memresource(dev, io, size); 13762306a36Sopenharmony_ci break; 13862306a36Sopenharmony_ci 13962306a36Sopenharmony_ci case SMALL_TAG_IRQ: 14062306a36Sopenharmony_ci if (len < 2 || len > 3) 14162306a36Sopenharmony_ci goto len_err; 14262306a36Sopenharmony_ci flags = 0; 14362306a36Sopenharmony_ci io = -1; 14462306a36Sopenharmony_ci mask = p[1] + p[2] * 256; 14562306a36Sopenharmony_ci for (i = 0; i < 16; i++, mask = mask >> 1) 14662306a36Sopenharmony_ci if (mask & 0x01) 14762306a36Sopenharmony_ci io = i; 14862306a36Sopenharmony_ci if (io != -1) 14962306a36Sopenharmony_ci pcibios_penalize_isa_irq(io, 1); 15062306a36Sopenharmony_ci else 15162306a36Sopenharmony_ci flags = IORESOURCE_DISABLED; 15262306a36Sopenharmony_ci pnp_add_irq_resource(dev, io, flags); 15362306a36Sopenharmony_ci break; 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_ci case SMALL_TAG_DMA: 15662306a36Sopenharmony_ci if (len != 2) 15762306a36Sopenharmony_ci goto len_err; 15862306a36Sopenharmony_ci flags = 0; 15962306a36Sopenharmony_ci io = -1; 16062306a36Sopenharmony_ci mask = p[1]; 16162306a36Sopenharmony_ci for (i = 0; i < 8; i++, mask = mask >> 1) 16262306a36Sopenharmony_ci if (mask & 0x01) 16362306a36Sopenharmony_ci io = i; 16462306a36Sopenharmony_ci if (io == -1) 16562306a36Sopenharmony_ci flags = IORESOURCE_DISABLED; 16662306a36Sopenharmony_ci pnp_add_dma_resource(dev, io, flags); 16762306a36Sopenharmony_ci break; 16862306a36Sopenharmony_ci 16962306a36Sopenharmony_ci case SMALL_TAG_PORT: 17062306a36Sopenharmony_ci if (len != 7) 17162306a36Sopenharmony_ci goto len_err; 17262306a36Sopenharmony_ci io = p[2] + p[3] * 256; 17362306a36Sopenharmony_ci size = p[7]; 17462306a36Sopenharmony_ci pnpbios_parse_allocated_ioresource(dev, io, size); 17562306a36Sopenharmony_ci break; 17662306a36Sopenharmony_ci 17762306a36Sopenharmony_ci case SMALL_TAG_VENDOR: 17862306a36Sopenharmony_ci /* do nothing */ 17962306a36Sopenharmony_ci break; 18062306a36Sopenharmony_ci 18162306a36Sopenharmony_ci case SMALL_TAG_FIXEDPORT: 18262306a36Sopenharmony_ci if (len != 3) 18362306a36Sopenharmony_ci goto len_err; 18462306a36Sopenharmony_ci io = p[1] + p[2] * 256; 18562306a36Sopenharmony_ci size = p[3]; 18662306a36Sopenharmony_ci pnpbios_parse_allocated_ioresource(dev, io, size); 18762306a36Sopenharmony_ci break; 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_ci case SMALL_TAG_END: 19062306a36Sopenharmony_ci p = p + 2; 19162306a36Sopenharmony_ci return (unsigned char *)p; 19262306a36Sopenharmony_ci break; 19362306a36Sopenharmony_ci 19462306a36Sopenharmony_ci default: /* an unknown tag */ 19562306a36Sopenharmony_cilen_err: 19662306a36Sopenharmony_ci dev_err(&dev->dev, "unknown tag %#x length %d\n", 19762306a36Sopenharmony_ci tag, len); 19862306a36Sopenharmony_ci break; 19962306a36Sopenharmony_ci } 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_ci /* continue to the next tag */ 20262306a36Sopenharmony_ci if (p[0] & LARGE_TAG) 20362306a36Sopenharmony_ci p += len + 3; 20462306a36Sopenharmony_ci else 20562306a36Sopenharmony_ci p += len + 1; 20662306a36Sopenharmony_ci } 20762306a36Sopenharmony_ci 20862306a36Sopenharmony_ci dev_err(&dev->dev, "no end tag in resource structure\n"); 20962306a36Sopenharmony_ci 21062306a36Sopenharmony_ci return NULL; 21162306a36Sopenharmony_ci} 21262306a36Sopenharmony_ci 21362306a36Sopenharmony_ci/* 21462306a36Sopenharmony_ci * Resource Configuration Options 21562306a36Sopenharmony_ci */ 21662306a36Sopenharmony_ci 21762306a36Sopenharmony_cistatic __init void pnpbios_parse_mem_option(struct pnp_dev *dev, 21862306a36Sopenharmony_ci unsigned char *p, int size, 21962306a36Sopenharmony_ci unsigned int option_flags) 22062306a36Sopenharmony_ci{ 22162306a36Sopenharmony_ci resource_size_t min, max, align, len; 22262306a36Sopenharmony_ci unsigned char flags; 22362306a36Sopenharmony_ci 22462306a36Sopenharmony_ci min = ((p[5] << 8) | p[4]) << 8; 22562306a36Sopenharmony_ci max = ((p[7] << 8) | p[6]) << 8; 22662306a36Sopenharmony_ci align = (p[9] << 8) | p[8]; 22762306a36Sopenharmony_ci len = ((p[11] << 8) | p[10]) << 8; 22862306a36Sopenharmony_ci flags = p[3]; 22962306a36Sopenharmony_ci pnp_register_mem_resource(dev, option_flags, min, max, align, len, 23062306a36Sopenharmony_ci flags); 23162306a36Sopenharmony_ci} 23262306a36Sopenharmony_ci 23362306a36Sopenharmony_cistatic __init void pnpbios_parse_mem32_option(struct pnp_dev *dev, 23462306a36Sopenharmony_ci unsigned char *p, int size, 23562306a36Sopenharmony_ci unsigned int option_flags) 23662306a36Sopenharmony_ci{ 23762306a36Sopenharmony_ci resource_size_t min, max, align, len; 23862306a36Sopenharmony_ci unsigned char flags; 23962306a36Sopenharmony_ci 24062306a36Sopenharmony_ci min = (p[7] << 24) | (p[6] << 16) | (p[5] << 8) | p[4]; 24162306a36Sopenharmony_ci max = (p[11] << 24) | (p[10] << 16) | (p[9] << 8) | p[8]; 24262306a36Sopenharmony_ci align = (p[15] << 24) | (p[14] << 16) | (p[13] << 8) | p[12]; 24362306a36Sopenharmony_ci len = (p[19] << 24) | (p[18] << 16) | (p[17] << 8) | p[16]; 24462306a36Sopenharmony_ci flags = p[3]; 24562306a36Sopenharmony_ci pnp_register_mem_resource(dev, option_flags, min, max, align, len, 24662306a36Sopenharmony_ci flags); 24762306a36Sopenharmony_ci} 24862306a36Sopenharmony_ci 24962306a36Sopenharmony_cistatic __init void pnpbios_parse_fixed_mem32_option(struct pnp_dev *dev, 25062306a36Sopenharmony_ci unsigned char *p, int size, 25162306a36Sopenharmony_ci unsigned int option_flags) 25262306a36Sopenharmony_ci{ 25362306a36Sopenharmony_ci resource_size_t base, len; 25462306a36Sopenharmony_ci unsigned char flags; 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_ci base = (p[7] << 24) | (p[6] << 16) | (p[5] << 8) | p[4]; 25762306a36Sopenharmony_ci len = (p[11] << 24) | (p[10] << 16) | (p[9] << 8) | p[8]; 25862306a36Sopenharmony_ci flags = p[3]; 25962306a36Sopenharmony_ci pnp_register_mem_resource(dev, option_flags, base, base, 0, len, flags); 26062306a36Sopenharmony_ci} 26162306a36Sopenharmony_ci 26262306a36Sopenharmony_cistatic __init void pnpbios_parse_irq_option(struct pnp_dev *dev, 26362306a36Sopenharmony_ci unsigned char *p, int size, 26462306a36Sopenharmony_ci unsigned int option_flags) 26562306a36Sopenharmony_ci{ 26662306a36Sopenharmony_ci unsigned long bits; 26762306a36Sopenharmony_ci pnp_irq_mask_t map; 26862306a36Sopenharmony_ci unsigned char flags = IORESOURCE_IRQ_HIGHEDGE; 26962306a36Sopenharmony_ci 27062306a36Sopenharmony_ci bits = (p[2] << 8) | p[1]; 27162306a36Sopenharmony_ci 27262306a36Sopenharmony_ci bitmap_zero(map.bits, PNP_IRQ_NR); 27362306a36Sopenharmony_ci bitmap_copy(map.bits, &bits, 16); 27462306a36Sopenharmony_ci 27562306a36Sopenharmony_ci if (size > 2) 27662306a36Sopenharmony_ci flags = p[3]; 27762306a36Sopenharmony_ci 27862306a36Sopenharmony_ci pnp_register_irq_resource(dev, option_flags, &map, flags); 27962306a36Sopenharmony_ci} 28062306a36Sopenharmony_ci 28162306a36Sopenharmony_cistatic __init void pnpbios_parse_dma_option(struct pnp_dev *dev, 28262306a36Sopenharmony_ci unsigned char *p, int size, 28362306a36Sopenharmony_ci unsigned int option_flags) 28462306a36Sopenharmony_ci{ 28562306a36Sopenharmony_ci pnp_register_dma_resource(dev, option_flags, p[1], p[2]); 28662306a36Sopenharmony_ci} 28762306a36Sopenharmony_ci 28862306a36Sopenharmony_cistatic __init void pnpbios_parse_port_option(struct pnp_dev *dev, 28962306a36Sopenharmony_ci unsigned char *p, int size, 29062306a36Sopenharmony_ci unsigned int option_flags) 29162306a36Sopenharmony_ci{ 29262306a36Sopenharmony_ci resource_size_t min, max, align, len; 29362306a36Sopenharmony_ci unsigned char flags; 29462306a36Sopenharmony_ci 29562306a36Sopenharmony_ci min = (p[3] << 8) | p[2]; 29662306a36Sopenharmony_ci max = (p[5] << 8) | p[4]; 29762306a36Sopenharmony_ci align = p[6]; 29862306a36Sopenharmony_ci len = p[7]; 29962306a36Sopenharmony_ci flags = p[1] ? IORESOURCE_IO_16BIT_ADDR : 0; 30062306a36Sopenharmony_ci pnp_register_port_resource(dev, option_flags, min, max, align, len, 30162306a36Sopenharmony_ci flags); 30262306a36Sopenharmony_ci} 30362306a36Sopenharmony_ci 30462306a36Sopenharmony_cistatic __init void pnpbios_parse_fixed_port_option(struct pnp_dev *dev, 30562306a36Sopenharmony_ci unsigned char *p, int size, 30662306a36Sopenharmony_ci unsigned int option_flags) 30762306a36Sopenharmony_ci{ 30862306a36Sopenharmony_ci resource_size_t base, len; 30962306a36Sopenharmony_ci 31062306a36Sopenharmony_ci base = (p[2] << 8) | p[1]; 31162306a36Sopenharmony_ci len = p[3]; 31262306a36Sopenharmony_ci pnp_register_port_resource(dev, option_flags, base, base, 0, len, 31362306a36Sopenharmony_ci IORESOURCE_IO_FIXED); 31462306a36Sopenharmony_ci} 31562306a36Sopenharmony_ci 31662306a36Sopenharmony_cistatic __init unsigned char * 31762306a36Sopenharmony_cipnpbios_parse_resource_option_data(unsigned char *p, unsigned char *end, 31862306a36Sopenharmony_ci struct pnp_dev *dev) 31962306a36Sopenharmony_ci{ 32062306a36Sopenharmony_ci unsigned int len, tag; 32162306a36Sopenharmony_ci int priority; 32262306a36Sopenharmony_ci unsigned int option_flags; 32362306a36Sopenharmony_ci 32462306a36Sopenharmony_ci if (!p) 32562306a36Sopenharmony_ci return NULL; 32662306a36Sopenharmony_ci 32762306a36Sopenharmony_ci pnp_dbg(&dev->dev, "parse resource options\n"); 32862306a36Sopenharmony_ci option_flags = 0; 32962306a36Sopenharmony_ci while ((char *)p < (char *)end) { 33062306a36Sopenharmony_ci 33162306a36Sopenharmony_ci /* determine the type of tag */ 33262306a36Sopenharmony_ci if (p[0] & LARGE_TAG) { /* large tag */ 33362306a36Sopenharmony_ci len = (p[2] << 8) | p[1]; 33462306a36Sopenharmony_ci tag = p[0]; 33562306a36Sopenharmony_ci } else { /* small tag */ 33662306a36Sopenharmony_ci len = p[0] & 0x07; 33762306a36Sopenharmony_ci tag = ((p[0] >> 3) & 0x0f); 33862306a36Sopenharmony_ci } 33962306a36Sopenharmony_ci 34062306a36Sopenharmony_ci switch (tag) { 34162306a36Sopenharmony_ci 34262306a36Sopenharmony_ci case LARGE_TAG_MEM: 34362306a36Sopenharmony_ci if (len != 9) 34462306a36Sopenharmony_ci goto len_err; 34562306a36Sopenharmony_ci pnpbios_parse_mem_option(dev, p, len, option_flags); 34662306a36Sopenharmony_ci break; 34762306a36Sopenharmony_ci 34862306a36Sopenharmony_ci case LARGE_TAG_MEM32: 34962306a36Sopenharmony_ci if (len != 17) 35062306a36Sopenharmony_ci goto len_err; 35162306a36Sopenharmony_ci pnpbios_parse_mem32_option(dev, p, len, option_flags); 35262306a36Sopenharmony_ci break; 35362306a36Sopenharmony_ci 35462306a36Sopenharmony_ci case LARGE_TAG_FIXEDMEM32: 35562306a36Sopenharmony_ci if (len != 9) 35662306a36Sopenharmony_ci goto len_err; 35762306a36Sopenharmony_ci pnpbios_parse_fixed_mem32_option(dev, p, len, 35862306a36Sopenharmony_ci option_flags); 35962306a36Sopenharmony_ci break; 36062306a36Sopenharmony_ci 36162306a36Sopenharmony_ci case SMALL_TAG_IRQ: 36262306a36Sopenharmony_ci if (len < 2 || len > 3) 36362306a36Sopenharmony_ci goto len_err; 36462306a36Sopenharmony_ci pnpbios_parse_irq_option(dev, p, len, option_flags); 36562306a36Sopenharmony_ci break; 36662306a36Sopenharmony_ci 36762306a36Sopenharmony_ci case SMALL_TAG_DMA: 36862306a36Sopenharmony_ci if (len != 2) 36962306a36Sopenharmony_ci goto len_err; 37062306a36Sopenharmony_ci pnpbios_parse_dma_option(dev, p, len, option_flags); 37162306a36Sopenharmony_ci break; 37262306a36Sopenharmony_ci 37362306a36Sopenharmony_ci case SMALL_TAG_PORT: 37462306a36Sopenharmony_ci if (len != 7) 37562306a36Sopenharmony_ci goto len_err; 37662306a36Sopenharmony_ci pnpbios_parse_port_option(dev, p, len, option_flags); 37762306a36Sopenharmony_ci break; 37862306a36Sopenharmony_ci 37962306a36Sopenharmony_ci case SMALL_TAG_VENDOR: 38062306a36Sopenharmony_ci /* do nothing */ 38162306a36Sopenharmony_ci break; 38262306a36Sopenharmony_ci 38362306a36Sopenharmony_ci case SMALL_TAG_FIXEDPORT: 38462306a36Sopenharmony_ci if (len != 3) 38562306a36Sopenharmony_ci goto len_err; 38662306a36Sopenharmony_ci pnpbios_parse_fixed_port_option(dev, p, len, 38762306a36Sopenharmony_ci option_flags); 38862306a36Sopenharmony_ci break; 38962306a36Sopenharmony_ci 39062306a36Sopenharmony_ci case SMALL_TAG_STARTDEP: 39162306a36Sopenharmony_ci if (len > 1) 39262306a36Sopenharmony_ci goto len_err; 39362306a36Sopenharmony_ci priority = PNP_RES_PRIORITY_ACCEPTABLE; 39462306a36Sopenharmony_ci if (len > 0) 39562306a36Sopenharmony_ci priority = p[1]; 39662306a36Sopenharmony_ci option_flags = pnp_new_dependent_set(dev, priority); 39762306a36Sopenharmony_ci break; 39862306a36Sopenharmony_ci 39962306a36Sopenharmony_ci case SMALL_TAG_ENDDEP: 40062306a36Sopenharmony_ci if (len != 0) 40162306a36Sopenharmony_ci goto len_err; 40262306a36Sopenharmony_ci option_flags = 0; 40362306a36Sopenharmony_ci break; 40462306a36Sopenharmony_ci 40562306a36Sopenharmony_ci case SMALL_TAG_END: 40662306a36Sopenharmony_ci return p + 2; 40762306a36Sopenharmony_ci 40862306a36Sopenharmony_ci default: /* an unknown tag */ 40962306a36Sopenharmony_cilen_err: 41062306a36Sopenharmony_ci dev_err(&dev->dev, "unknown tag %#x length %d\n", 41162306a36Sopenharmony_ci tag, len); 41262306a36Sopenharmony_ci break; 41362306a36Sopenharmony_ci } 41462306a36Sopenharmony_ci 41562306a36Sopenharmony_ci /* continue to the next tag */ 41662306a36Sopenharmony_ci if (p[0] & LARGE_TAG) 41762306a36Sopenharmony_ci p += len + 3; 41862306a36Sopenharmony_ci else 41962306a36Sopenharmony_ci p += len + 1; 42062306a36Sopenharmony_ci } 42162306a36Sopenharmony_ci 42262306a36Sopenharmony_ci dev_err(&dev->dev, "no end tag in resource structure\n"); 42362306a36Sopenharmony_ci 42462306a36Sopenharmony_ci return NULL; 42562306a36Sopenharmony_ci} 42662306a36Sopenharmony_ci 42762306a36Sopenharmony_ci/* 42862306a36Sopenharmony_ci * Compatible Device IDs 42962306a36Sopenharmony_ci */ 43062306a36Sopenharmony_ci 43162306a36Sopenharmony_cistatic unsigned char *pnpbios_parse_compatible_ids(unsigned char *p, 43262306a36Sopenharmony_ci unsigned char *end, 43362306a36Sopenharmony_ci struct pnp_dev *dev) 43462306a36Sopenharmony_ci{ 43562306a36Sopenharmony_ci int len, tag; 43662306a36Sopenharmony_ci u32 eisa_id; 43762306a36Sopenharmony_ci char id[8]; 43862306a36Sopenharmony_ci struct pnp_id *dev_id; 43962306a36Sopenharmony_ci 44062306a36Sopenharmony_ci if (!p) 44162306a36Sopenharmony_ci return NULL; 44262306a36Sopenharmony_ci 44362306a36Sopenharmony_ci while ((char *)p < (char *)end) { 44462306a36Sopenharmony_ci 44562306a36Sopenharmony_ci /* determine the type of tag */ 44662306a36Sopenharmony_ci if (p[0] & LARGE_TAG) { /* large tag */ 44762306a36Sopenharmony_ci len = (p[2] << 8) | p[1]; 44862306a36Sopenharmony_ci tag = p[0]; 44962306a36Sopenharmony_ci } else { /* small tag */ 45062306a36Sopenharmony_ci len = p[0] & 0x07; 45162306a36Sopenharmony_ci tag = ((p[0] >> 3) & 0x0f); 45262306a36Sopenharmony_ci } 45362306a36Sopenharmony_ci 45462306a36Sopenharmony_ci switch (tag) { 45562306a36Sopenharmony_ci 45662306a36Sopenharmony_ci case LARGE_TAG_ANSISTR: 45762306a36Sopenharmony_ci strncpy(dev->name, p + 3, 45862306a36Sopenharmony_ci len >= PNP_NAME_LEN ? PNP_NAME_LEN - 2 : len); 45962306a36Sopenharmony_ci dev->name[len >= 46062306a36Sopenharmony_ci PNP_NAME_LEN ? PNP_NAME_LEN - 1 : len] = '\0'; 46162306a36Sopenharmony_ci break; 46262306a36Sopenharmony_ci 46362306a36Sopenharmony_ci case SMALL_TAG_COMPATDEVID: /* compatible ID */ 46462306a36Sopenharmony_ci if (len != 4) 46562306a36Sopenharmony_ci goto len_err; 46662306a36Sopenharmony_ci eisa_id = p[1] | p[2] << 8 | p[3] << 16 | p[4] << 24; 46762306a36Sopenharmony_ci pnp_eisa_id_to_string(eisa_id & PNP_EISA_ID_MASK, id); 46862306a36Sopenharmony_ci dev_id = pnp_add_id(dev, id); 46962306a36Sopenharmony_ci if (!dev_id) 47062306a36Sopenharmony_ci return NULL; 47162306a36Sopenharmony_ci break; 47262306a36Sopenharmony_ci 47362306a36Sopenharmony_ci case SMALL_TAG_END: 47462306a36Sopenharmony_ci p = p + 2; 47562306a36Sopenharmony_ci return (unsigned char *)p; 47662306a36Sopenharmony_ci break; 47762306a36Sopenharmony_ci 47862306a36Sopenharmony_ci default: /* an unknown tag */ 47962306a36Sopenharmony_cilen_err: 48062306a36Sopenharmony_ci dev_err(&dev->dev, "unknown tag %#x length %d\n", 48162306a36Sopenharmony_ci tag, len); 48262306a36Sopenharmony_ci break; 48362306a36Sopenharmony_ci } 48462306a36Sopenharmony_ci 48562306a36Sopenharmony_ci /* continue to the next tag */ 48662306a36Sopenharmony_ci if (p[0] & LARGE_TAG) 48762306a36Sopenharmony_ci p += len + 3; 48862306a36Sopenharmony_ci else 48962306a36Sopenharmony_ci p += len + 1; 49062306a36Sopenharmony_ci } 49162306a36Sopenharmony_ci 49262306a36Sopenharmony_ci dev_err(&dev->dev, "no end tag in resource structure\n"); 49362306a36Sopenharmony_ci 49462306a36Sopenharmony_ci return NULL; 49562306a36Sopenharmony_ci} 49662306a36Sopenharmony_ci 49762306a36Sopenharmony_ci/* 49862306a36Sopenharmony_ci * Allocated Resource Encoding 49962306a36Sopenharmony_ci */ 50062306a36Sopenharmony_ci 50162306a36Sopenharmony_cistatic void pnpbios_encode_mem(struct pnp_dev *dev, unsigned char *p, 50262306a36Sopenharmony_ci struct resource *res) 50362306a36Sopenharmony_ci{ 50462306a36Sopenharmony_ci unsigned long base; 50562306a36Sopenharmony_ci unsigned long len; 50662306a36Sopenharmony_ci 50762306a36Sopenharmony_ci if (pnp_resource_enabled(res)) { 50862306a36Sopenharmony_ci base = res->start; 50962306a36Sopenharmony_ci len = resource_size(res); 51062306a36Sopenharmony_ci } else { 51162306a36Sopenharmony_ci base = 0; 51262306a36Sopenharmony_ci len = 0; 51362306a36Sopenharmony_ci } 51462306a36Sopenharmony_ci 51562306a36Sopenharmony_ci p[4] = (base >> 8) & 0xff; 51662306a36Sopenharmony_ci p[5] = ((base >> 8) >> 8) & 0xff; 51762306a36Sopenharmony_ci p[6] = (base >> 8) & 0xff; 51862306a36Sopenharmony_ci p[7] = ((base >> 8) >> 8) & 0xff; 51962306a36Sopenharmony_ci p[10] = (len >> 8) & 0xff; 52062306a36Sopenharmony_ci p[11] = ((len >> 8) >> 8) & 0xff; 52162306a36Sopenharmony_ci 52262306a36Sopenharmony_ci pnp_dbg(&dev->dev, " encode mem %#lx-%#lx\n", base, base + len - 1); 52362306a36Sopenharmony_ci} 52462306a36Sopenharmony_ci 52562306a36Sopenharmony_cistatic void pnpbios_encode_mem32(struct pnp_dev *dev, unsigned char *p, 52662306a36Sopenharmony_ci struct resource *res) 52762306a36Sopenharmony_ci{ 52862306a36Sopenharmony_ci unsigned long base; 52962306a36Sopenharmony_ci unsigned long len; 53062306a36Sopenharmony_ci 53162306a36Sopenharmony_ci if (pnp_resource_enabled(res)) { 53262306a36Sopenharmony_ci base = res->start; 53362306a36Sopenharmony_ci len = resource_size(res); 53462306a36Sopenharmony_ci } else { 53562306a36Sopenharmony_ci base = 0; 53662306a36Sopenharmony_ci len = 0; 53762306a36Sopenharmony_ci } 53862306a36Sopenharmony_ci 53962306a36Sopenharmony_ci p[4] = base & 0xff; 54062306a36Sopenharmony_ci p[5] = (base >> 8) & 0xff; 54162306a36Sopenharmony_ci p[6] = (base >> 16) & 0xff; 54262306a36Sopenharmony_ci p[7] = (base >> 24) & 0xff; 54362306a36Sopenharmony_ci p[8] = base & 0xff; 54462306a36Sopenharmony_ci p[9] = (base >> 8) & 0xff; 54562306a36Sopenharmony_ci p[10] = (base >> 16) & 0xff; 54662306a36Sopenharmony_ci p[11] = (base >> 24) & 0xff; 54762306a36Sopenharmony_ci p[16] = len & 0xff; 54862306a36Sopenharmony_ci p[17] = (len >> 8) & 0xff; 54962306a36Sopenharmony_ci p[18] = (len >> 16) & 0xff; 55062306a36Sopenharmony_ci p[19] = (len >> 24) & 0xff; 55162306a36Sopenharmony_ci 55262306a36Sopenharmony_ci pnp_dbg(&dev->dev, " encode mem32 %#lx-%#lx\n", base, base + len - 1); 55362306a36Sopenharmony_ci} 55462306a36Sopenharmony_ci 55562306a36Sopenharmony_cistatic void pnpbios_encode_fixed_mem32(struct pnp_dev *dev, unsigned char *p, 55662306a36Sopenharmony_ci struct resource *res) 55762306a36Sopenharmony_ci{ 55862306a36Sopenharmony_ci unsigned long base; 55962306a36Sopenharmony_ci unsigned long len; 56062306a36Sopenharmony_ci 56162306a36Sopenharmony_ci if (pnp_resource_enabled(res)) { 56262306a36Sopenharmony_ci base = res->start; 56362306a36Sopenharmony_ci len = resource_size(res); 56462306a36Sopenharmony_ci } else { 56562306a36Sopenharmony_ci base = 0; 56662306a36Sopenharmony_ci len = 0; 56762306a36Sopenharmony_ci } 56862306a36Sopenharmony_ci 56962306a36Sopenharmony_ci p[4] = base & 0xff; 57062306a36Sopenharmony_ci p[5] = (base >> 8) & 0xff; 57162306a36Sopenharmony_ci p[6] = (base >> 16) & 0xff; 57262306a36Sopenharmony_ci p[7] = (base >> 24) & 0xff; 57362306a36Sopenharmony_ci p[8] = len & 0xff; 57462306a36Sopenharmony_ci p[9] = (len >> 8) & 0xff; 57562306a36Sopenharmony_ci p[10] = (len >> 16) & 0xff; 57662306a36Sopenharmony_ci p[11] = (len >> 24) & 0xff; 57762306a36Sopenharmony_ci 57862306a36Sopenharmony_ci pnp_dbg(&dev->dev, " encode fixed_mem32 %#lx-%#lx\n", base, 57962306a36Sopenharmony_ci base + len - 1); 58062306a36Sopenharmony_ci} 58162306a36Sopenharmony_ci 58262306a36Sopenharmony_cistatic void pnpbios_encode_irq(struct pnp_dev *dev, unsigned char *p, 58362306a36Sopenharmony_ci struct resource *res) 58462306a36Sopenharmony_ci{ 58562306a36Sopenharmony_ci unsigned long map; 58662306a36Sopenharmony_ci 58762306a36Sopenharmony_ci if (pnp_resource_enabled(res)) 58862306a36Sopenharmony_ci map = 1 << res->start; 58962306a36Sopenharmony_ci else 59062306a36Sopenharmony_ci map = 0; 59162306a36Sopenharmony_ci 59262306a36Sopenharmony_ci p[1] = map & 0xff; 59362306a36Sopenharmony_ci p[2] = (map >> 8) & 0xff; 59462306a36Sopenharmony_ci 59562306a36Sopenharmony_ci pnp_dbg(&dev->dev, " encode irq mask %#lx\n", map); 59662306a36Sopenharmony_ci} 59762306a36Sopenharmony_ci 59862306a36Sopenharmony_cistatic void pnpbios_encode_dma(struct pnp_dev *dev, unsigned char *p, 59962306a36Sopenharmony_ci struct resource *res) 60062306a36Sopenharmony_ci{ 60162306a36Sopenharmony_ci unsigned long map; 60262306a36Sopenharmony_ci 60362306a36Sopenharmony_ci if (pnp_resource_enabled(res)) 60462306a36Sopenharmony_ci map = 1 << res->start; 60562306a36Sopenharmony_ci else 60662306a36Sopenharmony_ci map = 0; 60762306a36Sopenharmony_ci 60862306a36Sopenharmony_ci p[1] = map & 0xff; 60962306a36Sopenharmony_ci 61062306a36Sopenharmony_ci pnp_dbg(&dev->dev, " encode dma mask %#lx\n", map); 61162306a36Sopenharmony_ci} 61262306a36Sopenharmony_ci 61362306a36Sopenharmony_cistatic void pnpbios_encode_port(struct pnp_dev *dev, unsigned char *p, 61462306a36Sopenharmony_ci struct resource *res) 61562306a36Sopenharmony_ci{ 61662306a36Sopenharmony_ci unsigned long base; 61762306a36Sopenharmony_ci unsigned long len; 61862306a36Sopenharmony_ci 61962306a36Sopenharmony_ci if (pnp_resource_enabled(res)) { 62062306a36Sopenharmony_ci base = res->start; 62162306a36Sopenharmony_ci len = resource_size(res); 62262306a36Sopenharmony_ci } else { 62362306a36Sopenharmony_ci base = 0; 62462306a36Sopenharmony_ci len = 0; 62562306a36Sopenharmony_ci } 62662306a36Sopenharmony_ci 62762306a36Sopenharmony_ci p[2] = base & 0xff; 62862306a36Sopenharmony_ci p[3] = (base >> 8) & 0xff; 62962306a36Sopenharmony_ci p[4] = base & 0xff; 63062306a36Sopenharmony_ci p[5] = (base >> 8) & 0xff; 63162306a36Sopenharmony_ci p[7] = len & 0xff; 63262306a36Sopenharmony_ci 63362306a36Sopenharmony_ci pnp_dbg(&dev->dev, " encode io %#lx-%#lx\n", base, base + len - 1); 63462306a36Sopenharmony_ci} 63562306a36Sopenharmony_ci 63662306a36Sopenharmony_cistatic void pnpbios_encode_fixed_port(struct pnp_dev *dev, unsigned char *p, 63762306a36Sopenharmony_ci struct resource *res) 63862306a36Sopenharmony_ci{ 63962306a36Sopenharmony_ci unsigned long base = res->start; 64062306a36Sopenharmony_ci unsigned long len = resource_size(res); 64162306a36Sopenharmony_ci 64262306a36Sopenharmony_ci if (pnp_resource_enabled(res)) { 64362306a36Sopenharmony_ci base = res->start; 64462306a36Sopenharmony_ci len = resource_size(res); 64562306a36Sopenharmony_ci } else { 64662306a36Sopenharmony_ci base = 0; 64762306a36Sopenharmony_ci len = 0; 64862306a36Sopenharmony_ci } 64962306a36Sopenharmony_ci 65062306a36Sopenharmony_ci p[1] = base & 0xff; 65162306a36Sopenharmony_ci p[2] = (base >> 8) & 0xff; 65262306a36Sopenharmony_ci p[3] = len & 0xff; 65362306a36Sopenharmony_ci 65462306a36Sopenharmony_ci pnp_dbg(&dev->dev, " encode fixed_io %#lx-%#lx\n", base, 65562306a36Sopenharmony_ci base + len - 1); 65662306a36Sopenharmony_ci} 65762306a36Sopenharmony_ci 65862306a36Sopenharmony_cistatic unsigned char *pnpbios_encode_allocated_resource_data(struct pnp_dev 65962306a36Sopenharmony_ci *dev, 66062306a36Sopenharmony_ci unsigned char *p, 66162306a36Sopenharmony_ci unsigned char *end) 66262306a36Sopenharmony_ci{ 66362306a36Sopenharmony_ci unsigned int len, tag; 66462306a36Sopenharmony_ci int port = 0, irq = 0, dma = 0, mem = 0; 66562306a36Sopenharmony_ci 66662306a36Sopenharmony_ci if (!p) 66762306a36Sopenharmony_ci return NULL; 66862306a36Sopenharmony_ci 66962306a36Sopenharmony_ci while ((char *)p < (char *)end) { 67062306a36Sopenharmony_ci 67162306a36Sopenharmony_ci /* determine the type of tag */ 67262306a36Sopenharmony_ci if (p[0] & LARGE_TAG) { /* large tag */ 67362306a36Sopenharmony_ci len = (p[2] << 8) | p[1]; 67462306a36Sopenharmony_ci tag = p[0]; 67562306a36Sopenharmony_ci } else { /* small tag */ 67662306a36Sopenharmony_ci len = p[0] & 0x07; 67762306a36Sopenharmony_ci tag = ((p[0] >> 3) & 0x0f); 67862306a36Sopenharmony_ci } 67962306a36Sopenharmony_ci 68062306a36Sopenharmony_ci switch (tag) { 68162306a36Sopenharmony_ci 68262306a36Sopenharmony_ci case LARGE_TAG_MEM: 68362306a36Sopenharmony_ci if (len != 9) 68462306a36Sopenharmony_ci goto len_err; 68562306a36Sopenharmony_ci pnpbios_encode_mem(dev, p, 68662306a36Sopenharmony_ci pnp_get_resource(dev, IORESOURCE_MEM, mem)); 68762306a36Sopenharmony_ci mem++; 68862306a36Sopenharmony_ci break; 68962306a36Sopenharmony_ci 69062306a36Sopenharmony_ci case LARGE_TAG_MEM32: 69162306a36Sopenharmony_ci if (len != 17) 69262306a36Sopenharmony_ci goto len_err; 69362306a36Sopenharmony_ci pnpbios_encode_mem32(dev, p, 69462306a36Sopenharmony_ci pnp_get_resource(dev, IORESOURCE_MEM, mem)); 69562306a36Sopenharmony_ci mem++; 69662306a36Sopenharmony_ci break; 69762306a36Sopenharmony_ci 69862306a36Sopenharmony_ci case LARGE_TAG_FIXEDMEM32: 69962306a36Sopenharmony_ci if (len != 9) 70062306a36Sopenharmony_ci goto len_err; 70162306a36Sopenharmony_ci pnpbios_encode_fixed_mem32(dev, p, 70262306a36Sopenharmony_ci pnp_get_resource(dev, IORESOURCE_MEM, mem)); 70362306a36Sopenharmony_ci mem++; 70462306a36Sopenharmony_ci break; 70562306a36Sopenharmony_ci 70662306a36Sopenharmony_ci case SMALL_TAG_IRQ: 70762306a36Sopenharmony_ci if (len < 2 || len > 3) 70862306a36Sopenharmony_ci goto len_err; 70962306a36Sopenharmony_ci pnpbios_encode_irq(dev, p, 71062306a36Sopenharmony_ci pnp_get_resource(dev, IORESOURCE_IRQ, irq)); 71162306a36Sopenharmony_ci irq++; 71262306a36Sopenharmony_ci break; 71362306a36Sopenharmony_ci 71462306a36Sopenharmony_ci case SMALL_TAG_DMA: 71562306a36Sopenharmony_ci if (len != 2) 71662306a36Sopenharmony_ci goto len_err; 71762306a36Sopenharmony_ci pnpbios_encode_dma(dev, p, 71862306a36Sopenharmony_ci pnp_get_resource(dev, IORESOURCE_DMA, dma)); 71962306a36Sopenharmony_ci dma++; 72062306a36Sopenharmony_ci break; 72162306a36Sopenharmony_ci 72262306a36Sopenharmony_ci case SMALL_TAG_PORT: 72362306a36Sopenharmony_ci if (len != 7) 72462306a36Sopenharmony_ci goto len_err; 72562306a36Sopenharmony_ci pnpbios_encode_port(dev, p, 72662306a36Sopenharmony_ci pnp_get_resource(dev, IORESOURCE_IO, port)); 72762306a36Sopenharmony_ci port++; 72862306a36Sopenharmony_ci break; 72962306a36Sopenharmony_ci 73062306a36Sopenharmony_ci case SMALL_TAG_VENDOR: 73162306a36Sopenharmony_ci /* do nothing */ 73262306a36Sopenharmony_ci break; 73362306a36Sopenharmony_ci 73462306a36Sopenharmony_ci case SMALL_TAG_FIXEDPORT: 73562306a36Sopenharmony_ci if (len != 3) 73662306a36Sopenharmony_ci goto len_err; 73762306a36Sopenharmony_ci pnpbios_encode_fixed_port(dev, p, 73862306a36Sopenharmony_ci pnp_get_resource(dev, IORESOURCE_IO, port)); 73962306a36Sopenharmony_ci port++; 74062306a36Sopenharmony_ci break; 74162306a36Sopenharmony_ci 74262306a36Sopenharmony_ci case SMALL_TAG_END: 74362306a36Sopenharmony_ci p = p + 2; 74462306a36Sopenharmony_ci return (unsigned char *)p; 74562306a36Sopenharmony_ci break; 74662306a36Sopenharmony_ci 74762306a36Sopenharmony_ci default: /* an unknown tag */ 74862306a36Sopenharmony_cilen_err: 74962306a36Sopenharmony_ci dev_err(&dev->dev, "unknown tag %#x length %d\n", 75062306a36Sopenharmony_ci tag, len); 75162306a36Sopenharmony_ci break; 75262306a36Sopenharmony_ci } 75362306a36Sopenharmony_ci 75462306a36Sopenharmony_ci /* continue to the next tag */ 75562306a36Sopenharmony_ci if (p[0] & LARGE_TAG) 75662306a36Sopenharmony_ci p += len + 3; 75762306a36Sopenharmony_ci else 75862306a36Sopenharmony_ci p += len + 1; 75962306a36Sopenharmony_ci } 76062306a36Sopenharmony_ci 76162306a36Sopenharmony_ci dev_err(&dev->dev, "no end tag in resource structure\n"); 76262306a36Sopenharmony_ci 76362306a36Sopenharmony_ci return NULL; 76462306a36Sopenharmony_ci} 76562306a36Sopenharmony_ci 76662306a36Sopenharmony_ci/* 76762306a36Sopenharmony_ci * Core Parsing Functions 76862306a36Sopenharmony_ci */ 76962306a36Sopenharmony_ci 77062306a36Sopenharmony_ciint __init pnpbios_parse_data_stream(struct pnp_dev *dev, 77162306a36Sopenharmony_ci struct pnp_bios_node *node) 77262306a36Sopenharmony_ci{ 77362306a36Sopenharmony_ci unsigned char *p = (char *)node->data; 77462306a36Sopenharmony_ci unsigned char *end = (char *)(node->data + node->size); 77562306a36Sopenharmony_ci 77662306a36Sopenharmony_ci p = pnpbios_parse_allocated_resource_data(dev, p, end); 77762306a36Sopenharmony_ci if (!p) 77862306a36Sopenharmony_ci return -EIO; 77962306a36Sopenharmony_ci p = pnpbios_parse_resource_option_data(p, end, dev); 78062306a36Sopenharmony_ci if (!p) 78162306a36Sopenharmony_ci return -EIO; 78262306a36Sopenharmony_ci p = pnpbios_parse_compatible_ids(p, end, dev); 78362306a36Sopenharmony_ci if (!p) 78462306a36Sopenharmony_ci return -EIO; 78562306a36Sopenharmony_ci return 0; 78662306a36Sopenharmony_ci} 78762306a36Sopenharmony_ci 78862306a36Sopenharmony_ciint pnpbios_read_resources_from_node(struct pnp_dev *dev, 78962306a36Sopenharmony_ci struct pnp_bios_node *node) 79062306a36Sopenharmony_ci{ 79162306a36Sopenharmony_ci unsigned char *p = (char *)node->data; 79262306a36Sopenharmony_ci unsigned char *end = (char *)(node->data + node->size); 79362306a36Sopenharmony_ci 79462306a36Sopenharmony_ci p = pnpbios_parse_allocated_resource_data(dev, p, end); 79562306a36Sopenharmony_ci if (!p) 79662306a36Sopenharmony_ci return -EIO; 79762306a36Sopenharmony_ci return 0; 79862306a36Sopenharmony_ci} 79962306a36Sopenharmony_ci 80062306a36Sopenharmony_ciint pnpbios_write_resources_to_node(struct pnp_dev *dev, 80162306a36Sopenharmony_ci struct pnp_bios_node *node) 80262306a36Sopenharmony_ci{ 80362306a36Sopenharmony_ci unsigned char *p = (char *)node->data; 80462306a36Sopenharmony_ci unsigned char *end = (char *)(node->data + node->size); 80562306a36Sopenharmony_ci 80662306a36Sopenharmony_ci p = pnpbios_encode_allocated_resource_data(dev, p, end); 80762306a36Sopenharmony_ci if (!p) 80862306a36Sopenharmony_ci return -EIO; 80962306a36Sopenharmony_ci return 0; 81062306a36Sopenharmony_ci} 811