0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035 #include <linux/types.h>
0036 #include <linux/init.h>
0037 #include <linux/linkage.h>
0038 #include <linux/kernel.h>
0039 #include <linux/device.h>
0040 #include <linux/pnp.h>
0041 #include <linux/mm.h>
0042 #include <linux/smp.h>
0043 #include <linux/slab.h>
0044 #include <linux/completion.h>
0045 #include <linux/spinlock.h>
0046 #include <linux/dmi.h>
0047 #include <linux/delay.h>
0048 #include <linux/acpi.h>
0049 #include <linux/freezer.h>
0050 #include <linux/kmod.h>
0051 #include <linux/kthread.h>
0052
0053 #include <asm/page.h>
0054 #include <asm/desc.h>
0055 #include <asm/byteorder.h>
0056
0057 #include "../base.h"
0058 #include "pnpbios.h"
0059
0060
0061
0062
0063
0064
0065
0066 static union pnp_bios_install_struct *pnp_bios_install = NULL;
0067
0068 int pnp_bios_present(void)
0069 {
0070 return (pnp_bios_install != NULL);
0071 }
0072
0073 struct pnp_dev_node_info node_info;
0074
0075
0076
0077
0078
0079
0080
0081 static struct completion unload_sem;
0082
0083
0084
0085
0086 static int pnp_dock_event(int dock, struct pnp_docking_station_info *info)
0087 {
0088 static char const sbin_pnpbios[] = "/sbin/pnpbios";
0089 char *argv[3], **envp, *buf, *scratch;
0090 int i = 0, value;
0091
0092 if (!(envp = kcalloc(20, sizeof(char *), GFP_KERNEL)))
0093 return -ENOMEM;
0094 if (!(buf = kzalloc(256, GFP_KERNEL))) {
0095 kfree(envp);
0096 return -ENOMEM;
0097 }
0098
0099
0100
0101
0102
0103 argv[0] = (char *)sbin_pnpbios;
0104 argv[1] = "dock";
0105 argv[2] = NULL;
0106
0107
0108 envp[i++] = "HOME=/";
0109 envp[i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
0110
0111 #ifdef DEBUG
0112
0113 envp[i++] = "DEBUG=kernel";
0114 #endif
0115
0116
0117
0118 scratch = buf;
0119
0120
0121 envp[i++] = scratch;
0122 scratch += sprintf(scratch, "ACTION=%s", dock ? "add" : "remove") + 1;
0123
0124
0125 envp[i++] = scratch;
0126 scratch += sprintf(scratch, "DOCK=%x/%x/%x",
0127 info->location_id, info->serial, info->capabilities);
0128 envp[i] = NULL;
0129
0130 value = call_usermodehelper(sbin_pnpbios, argv, envp, UMH_WAIT_EXEC);
0131 kfree(buf);
0132 kfree(envp);
0133 return 0;
0134 }
0135
0136
0137
0138
0139 static int pnp_dock_thread(void *unused)
0140 {
0141 static struct pnp_docking_station_info now;
0142 int docked = -1, d = 0;
0143
0144 set_freezable();
0145 while (1) {
0146 int status;
0147
0148
0149
0150
0151 msleep_interruptible(2000);
0152
0153 if (try_to_freeze())
0154 continue;
0155
0156 status = pnp_bios_dock_station_info(&now);
0157
0158 switch (status) {
0159
0160
0161
0162 case PNP_FUNCTION_NOT_SUPPORTED:
0163 kthread_complete_and_exit(&unload_sem, 0);
0164 case PNP_SYSTEM_NOT_DOCKED:
0165 d = 0;
0166 break;
0167 case PNP_SUCCESS:
0168 d = 1;
0169 break;
0170 default:
0171 pnpbios_print_status("pnp_dock_thread", status);
0172 printk(KERN_WARNING "PnPBIOS: disabling dock monitoring.\n");
0173 kthread_complete_and_exit(&unload_sem, 0);
0174 }
0175 if (d != docked) {
0176 if (pnp_dock_event(d, &now) == 0) {
0177 docked = d;
0178 #if 0
0179 printk(KERN_INFO
0180 "PnPBIOS: Docking station %stached\n",
0181 docked ? "at" : "de");
0182 #endif
0183 }
0184 }
0185 }
0186 kthread_complete_and_exit(&unload_sem, 0);
0187 }
0188
0189 static int pnpbios_get_resources(struct pnp_dev *dev)
0190 {
0191 u8 nodenum = dev->number;
0192 struct pnp_bios_node *node;
0193
0194 if (!pnpbios_is_dynamic(dev))
0195 return -EPERM;
0196
0197 pnp_dbg(&dev->dev, "get resources\n");
0198 node = kzalloc(node_info.max_node_size, GFP_KERNEL);
0199 if (!node)
0200 return -1;
0201 if (pnp_bios_get_dev_node(&nodenum, (char)PNPMODE_DYNAMIC, node)) {
0202 kfree(node);
0203 return -ENODEV;
0204 }
0205 pnpbios_read_resources_from_node(dev, node);
0206 dev->active = pnp_is_active(dev);
0207 kfree(node);
0208 return 0;
0209 }
0210
0211 static int pnpbios_set_resources(struct pnp_dev *dev)
0212 {
0213 u8 nodenum = dev->number;
0214 struct pnp_bios_node *node;
0215 int ret;
0216
0217 if (!pnpbios_is_dynamic(dev))
0218 return -EPERM;
0219
0220 pnp_dbg(&dev->dev, "set resources\n");
0221 node = kzalloc(node_info.max_node_size, GFP_KERNEL);
0222 if (!node)
0223 return -1;
0224 if (pnp_bios_get_dev_node(&nodenum, (char)PNPMODE_DYNAMIC, node)) {
0225 kfree(node);
0226 return -ENODEV;
0227 }
0228 if (pnpbios_write_resources_to_node(dev, node) < 0) {
0229 kfree(node);
0230 return -1;
0231 }
0232 ret = pnp_bios_set_dev_node(node->handle, (char)PNPMODE_DYNAMIC, node);
0233 kfree(node);
0234 if (ret > 0)
0235 ret = -1;
0236 return ret;
0237 }
0238
0239 static void pnpbios_zero_data_stream(struct pnp_bios_node *node)
0240 {
0241 unsigned char *p = (char *)node->data;
0242 unsigned char *end = (char *)(node->data + node->size);
0243 unsigned int len;
0244 int i;
0245
0246 while ((char *)p < (char *)end) {
0247 if (p[0] & 0x80) {
0248 len = (p[2] << 8) | p[1];
0249 p += 3;
0250 } else {
0251 if (((p[0] >> 3) & 0x0f) == 0x0f)
0252 return;
0253 len = p[0] & 0x07;
0254 p += 1;
0255 }
0256 for (i = 0; i < len; i++)
0257 p[i] = 0;
0258 p += len;
0259 }
0260 printk(KERN_ERR
0261 "PnPBIOS: Resource structure did not contain an end tag.\n");
0262 }
0263
0264 static int pnpbios_disable_resources(struct pnp_dev *dev)
0265 {
0266 struct pnp_bios_node *node;
0267 u8 nodenum = dev->number;
0268 int ret;
0269
0270 if (dev->flags & PNPBIOS_NO_DISABLE || !pnpbios_is_dynamic(dev))
0271 return -EPERM;
0272
0273 node = kzalloc(node_info.max_node_size, GFP_KERNEL);
0274 if (!node)
0275 return -ENOMEM;
0276
0277 if (pnp_bios_get_dev_node(&nodenum, (char)PNPMODE_DYNAMIC, node)) {
0278 kfree(node);
0279 return -ENODEV;
0280 }
0281 pnpbios_zero_data_stream(node);
0282
0283 ret = pnp_bios_set_dev_node(dev->number, (char)PNPMODE_DYNAMIC, node);
0284 kfree(node);
0285 if (ret > 0)
0286 ret = -1;
0287 return ret;
0288 }
0289
0290
0291
0292 struct pnp_protocol pnpbios_protocol = {
0293 .name = "Plug and Play BIOS",
0294 .get = pnpbios_get_resources,
0295 .set = pnpbios_set_resources,
0296 .disable = pnpbios_disable_resources,
0297 };
0298
0299 static int __init insert_device(struct pnp_bios_node *node)
0300 {
0301 struct pnp_dev *dev;
0302 char id[8];
0303 int error;
0304
0305
0306 list_for_each_entry(dev, &pnpbios_protocol.devices, protocol_list) {
0307 if (dev->number == node->handle)
0308 return -EEXIST;
0309 }
0310
0311 pnp_eisa_id_to_string(node->eisa_id & PNP_EISA_ID_MASK, id);
0312 dev = pnp_alloc_dev(&pnpbios_protocol, node->handle, id);
0313 if (!dev)
0314 return -ENOMEM;
0315
0316 pnpbios_parse_data_stream(dev, node);
0317 dev->active = pnp_is_active(dev);
0318 dev->flags = node->flags;
0319 if (!(dev->flags & PNPBIOS_NO_CONFIG))
0320 dev->capabilities |= PNP_CONFIGURABLE;
0321 if (!(dev->flags & PNPBIOS_NO_DISABLE) && pnpbios_is_dynamic(dev))
0322 dev->capabilities |= PNP_DISABLE;
0323 dev->capabilities |= PNP_READ;
0324 if (pnpbios_is_dynamic(dev))
0325 dev->capabilities |= PNP_WRITE;
0326 if (dev->flags & PNPBIOS_REMOVABLE)
0327 dev->capabilities |= PNP_REMOVABLE;
0328
0329
0330 if (!dev->active)
0331 pnp_init_resources(dev);
0332
0333 error = pnp_add_device(dev);
0334 if (error) {
0335 put_device(&dev->dev);
0336 return error;
0337 }
0338
0339 pnpbios_interface_attach_device(node);
0340
0341 return 0;
0342 }
0343
0344 static void __init build_devlist(void)
0345 {
0346 u8 nodenum;
0347 unsigned int nodes_got = 0;
0348 unsigned int devs = 0;
0349 struct pnp_bios_node *node;
0350
0351 node = kzalloc(node_info.max_node_size, GFP_KERNEL);
0352 if (!node)
0353 return;
0354
0355 for (nodenum = 0; nodenum < 0xff;) {
0356 u8 thisnodenum = nodenum;
0357
0358
0359
0360 if (!pnpbios_dont_use_current_config) {
0361 if (pnp_bios_get_dev_node
0362 (&nodenum, (char)PNPMODE_DYNAMIC, node))
0363 break;
0364 } else {
0365 if (pnp_bios_get_dev_node
0366 (&nodenum, (char)PNPMODE_STATIC, node))
0367 break;
0368 }
0369 nodes_got++;
0370 if (insert_device(node) == 0)
0371 devs++;
0372 if (nodenum <= thisnodenum) {
0373 printk(KERN_ERR
0374 "PnPBIOS: build_devlist: Node number 0x%x is out of sequence following node 0x%x. Aborting.\n",
0375 (unsigned int)nodenum,
0376 (unsigned int)thisnodenum);
0377 break;
0378 }
0379 }
0380 kfree(node);
0381
0382 printk(KERN_INFO
0383 "PnPBIOS: %i node%s reported by PnP BIOS; %i recorded by driver\n",
0384 nodes_got, nodes_got != 1 ? "s" : "", devs);
0385 }
0386
0387
0388
0389
0390
0391
0392
0393 static int pnpbios_disabled;
0394 int pnpbios_dont_use_current_config;
0395
0396 static int __init pnpbios_setup(char *str)
0397 {
0398 int invert;
0399
0400 while ((str != NULL) && (*str != '\0')) {
0401 if (strncmp(str, "off", 3) == 0)
0402 pnpbios_disabled = 1;
0403 if (strncmp(str, "on", 2) == 0)
0404 pnpbios_disabled = 0;
0405 invert = (strncmp(str, "no-", 3) == 0);
0406 if (invert)
0407 str += 3;
0408 if (strncmp(str, "curr", 4) == 0)
0409 pnpbios_dont_use_current_config = invert;
0410 str = strchr(str, ',');
0411 if (str != NULL)
0412 str += strspn(str, ", \t");
0413 }
0414
0415 return 1;
0416 }
0417
0418 __setup("pnpbios=", pnpbios_setup);
0419
0420
0421 #define PNP_SIGNATURE (('$' << 0) + ('P' << 8) + ('n' << 16) + ('P' << 24))
0422
0423 static int __init pnpbios_probe_system(void)
0424 {
0425 union pnp_bios_install_struct *check;
0426 u8 sum;
0427 int length, i;
0428
0429 printk(KERN_INFO "PnPBIOS: Scanning system for PnP BIOS support...\n");
0430
0431
0432
0433
0434
0435
0436 for (check = (union pnp_bios_install_struct *)__va(0xf0000);
0437 check < (union pnp_bios_install_struct *)__va(0xffff0);
0438 check = (void *)check + 16) {
0439 if (check->fields.signature != PNP_SIGNATURE)
0440 continue;
0441 printk(KERN_INFO
0442 "PnPBIOS: Found PnP BIOS installation structure at 0x%p\n",
0443 check);
0444 length = check->fields.length;
0445 if (!length) {
0446 printk(KERN_ERR
0447 "PnPBIOS: installation structure is invalid, skipping\n");
0448 continue;
0449 }
0450 for (sum = 0, i = 0; i < length; i++)
0451 sum += check->chars[i];
0452 if (sum) {
0453 printk(KERN_ERR
0454 "PnPBIOS: installation structure is corrupted, skipping\n");
0455 continue;
0456 }
0457 if (check->fields.version < 0x10) {
0458 printk(KERN_WARNING
0459 "PnPBIOS: PnP BIOS version %d.%d is not supported\n",
0460 check->fields.version >> 4,
0461 check->fields.version & 15);
0462 continue;
0463 }
0464 printk(KERN_INFO
0465 "PnPBIOS: PnP BIOS version %d.%d, entry 0x%x:0x%x, dseg 0x%x\n",
0466 check->fields.version >> 4, check->fields.version & 15,
0467 check->fields.pm16cseg, check->fields.pm16offset,
0468 check->fields.pm16dseg);
0469 pnp_bios_install = check;
0470 return 1;
0471 }
0472
0473 printk(KERN_INFO "PnPBIOS: PnP BIOS support was not detected.\n");
0474 return 0;
0475 }
0476
0477 static int __init exploding_pnp_bios(const struct dmi_system_id *d)
0478 {
0479 printk(KERN_WARNING "%s detected. Disabling PnPBIOS\n", d->ident);
0480 return 0;
0481 }
0482
0483 static const struct dmi_system_id pnpbios_dmi_table[] __initconst = {
0484 {
0485 .callback = exploding_pnp_bios,
0486 .ident = "Higraded P14H",
0487 .matches = {
0488 DMI_MATCH(DMI_BIOS_VENDOR, "American Megatrends Inc."),
0489 DMI_MATCH(DMI_BIOS_VERSION, "07.00T"),
0490 DMI_MATCH(DMI_SYS_VENDOR, "Higraded"),
0491 DMI_MATCH(DMI_PRODUCT_NAME, "P14H"),
0492 },
0493 },
0494 {
0495 .callback = exploding_pnp_bios,
0496 .ident = "ASUS P4P800",
0497 .matches = {
0498 DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer Inc."),
0499 DMI_MATCH(DMI_BOARD_NAME, "P4P800"),
0500 },
0501 },
0502 {}
0503 };
0504
0505 static int __init pnpbios_init(void)
0506 {
0507 int ret;
0508
0509 if (pnpbios_disabled || dmi_check_system(pnpbios_dmi_table) ||
0510 arch_pnpbios_disabled()) {
0511 printk(KERN_INFO "PnPBIOS: Disabled\n");
0512 return -ENODEV;
0513 }
0514
0515 #ifdef CONFIG_PNPACPI
0516 if (!acpi_disabled && !pnpacpi_disabled) {
0517 pnpbios_disabled = 1;
0518 printk(KERN_INFO "PnPBIOS: Disabled by ACPI PNP\n");
0519 return -ENODEV;
0520 }
0521 #endif
0522
0523
0524 if (!pnpbios_probe_system())
0525 return -ENODEV;
0526
0527
0528 pnpbios_calls_init(pnp_bios_install);
0529
0530
0531 ret = pnp_bios_dev_node_info(&node_info);
0532 if (ret) {
0533 printk(KERN_ERR
0534 "PnPBIOS: Unable to get node info. Aborting.\n");
0535 return ret;
0536 }
0537
0538
0539 ret = pnp_register_protocol(&pnpbios_protocol);
0540 if (ret) {
0541 printk(KERN_ERR
0542 "PnPBIOS: Unable to register driver. Aborting.\n");
0543 return ret;
0544 }
0545
0546
0547 ret = pnpbios_proc_init();
0548 if (ret)
0549 printk(KERN_ERR "PnPBIOS: Failed to create proc interface.\n");
0550
0551
0552 build_devlist();
0553
0554 pnp_platform_devices = 1;
0555 return 0;
0556 }
0557
0558 fs_initcall(pnpbios_init);
0559
0560 static int __init pnpbios_thread_init(void)
0561 {
0562 struct task_struct *task;
0563
0564 if (pnpbios_disabled)
0565 return 0;
0566
0567 init_completion(&unload_sem);
0568 task = kthread_run(pnp_dock_thread, NULL, "kpnpbiosd");
0569 return PTR_ERR_OR_ZERO(task);
0570 }
0571
0572
0573 device_initcall(pnpbios_thread_init);
0574
0575 EXPORT_SYMBOL(pnpbios_protocol);