aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/osl.c
diff options
context:
space:
mode:
authorLen Brown <len.brown@intel.com>2008-02-07 04:01:53 -0500
committerLen Brown <len.brown@intel.com>2008-02-07 04:01:53 -0500
commit81e242d0efafb319938d511b115088a5c4523c91 (patch)
treebe22aa41db2288fd7999524d719f333c766a367f /drivers/acpi/osl.c
parenta733a5da97b238e3e3167d3d0aee8fe1e8d04e97 (diff)
parent04d94886b47b5133915021dcfb1108a8576f6ea7 (diff)
Merge branches 'release' and 'dsdt-override' into release
Diffstat (limited to 'drivers/acpi/osl.c')
-rw-r--r--drivers/acpi/osl.c97
1 files changed, 93 insertions, 4 deletions
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index c2c585366fa6..27ccd68b8f46 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -91,6 +91,10 @@ static DEFINE_SPINLOCK(acpi_res_lock);
91#define OSI_STRING_LENGTH_MAX 64 /* arbitrary */ 91#define OSI_STRING_LENGTH_MAX 64 /* arbitrary */
92static char osi_additional_string[OSI_STRING_LENGTH_MAX]; 92static char osi_additional_string[OSI_STRING_LENGTH_MAX];
93 93
94#ifdef CONFIG_ACPI_CUSTOM_DSDT_INITRD
95static int acpi_no_initrd_override;
96#endif
97
94/* 98/*
95 * "Ode to _OSI(Linux)" 99 * "Ode to _OSI(Linux)"
96 * 100 *
@@ -329,6 +333,67 @@ acpi_os_predefined_override(const struct acpi_predefined_names *init_val,
329 return AE_OK; 333 return AE_OK;
330} 334}
331 335
336#ifdef CONFIG_ACPI_CUSTOM_DSDT_INITRD
337struct acpi_table_header *acpi_find_dsdt_initrd(void)
338{
339 struct file *firmware_file;
340 mm_segment_t oldfs;
341 unsigned long len, len2;
342 struct acpi_table_header *dsdt_buffer, *ret = NULL;
343 struct kstat stat;
344 char *ramfs_dsdt_name = "/DSDT.aml";
345
346 printk(KERN_INFO PREFIX "Checking initramfs for custom DSDT");
347
348 /*
349 * Never do this at home, only the user-space is allowed to open a file.
350 * The clean way would be to use the firmware loader.
351 * But this code must be run before there is any userspace available.
352 * A static/init firmware infrastructure doesn't exist yet...
353 */
354 if (vfs_stat(ramfs_dsdt_name, &stat) < 0)
355 return ret;
356
357 len = stat.size;
358 /* check especially against empty files */
359 if (len <= 4) {
360 printk(KERN_ERR PREFIX "Failed: DSDT only %lu bytes.\n", len);
361 return ret;
362 }
363
364 firmware_file = filp_open(ramfs_dsdt_name, O_RDONLY, 0);
365 if (IS_ERR(firmware_file)) {
366 printk(KERN_ERR PREFIX "Failed to open %s.\n", ramfs_dsdt_name);
367 return ret;
368 }
369
370 dsdt_buffer = kmalloc(len, GFP_ATOMIC);
371 if (!dsdt_buffer) {
372 printk(KERN_ERR PREFIX "Failed to allocate %lu bytes.\n", len);
373 goto err;
374 }
375
376 oldfs = get_fs();
377 set_fs(KERNEL_DS);
378 len2 = vfs_read(firmware_file, (char __user *)dsdt_buffer, len,
379 &firmware_file->f_pos);
380 set_fs(oldfs);
381 if (len2 < len) {
382 printk(KERN_ERR PREFIX "Failed to read %lu bytes from %s.\n",
383 len, ramfs_dsdt_name);
384 ACPI_FREE(dsdt_buffer);
385 goto err;
386 }
387
388 printk(KERN_INFO PREFIX "Found %lu byte DSDT in %s.\n",
389 len, ramfs_dsdt_name);
390 ret = dsdt_buffer;
391err:
392 filp_close(firmware_file, NULL);
393 return ret;
394}
395#endif
396
332acpi_status 397acpi_status
333acpi_os_table_override(struct acpi_table_header * existing_table, 398acpi_os_table_override(struct acpi_table_header * existing_table,
334 struct acpi_table_header ** new_table) 399 struct acpi_table_header ** new_table)
@@ -336,17 +401,41 @@ acpi_os_table_override(struct acpi_table_header * existing_table,
336 if (!existing_table || !new_table) 401 if (!existing_table || !new_table)
337 return AE_BAD_PARAMETER; 402 return AE_BAD_PARAMETER;
338 403
404 *new_table = NULL;
405
339#ifdef CONFIG_ACPI_CUSTOM_DSDT 406#ifdef CONFIG_ACPI_CUSTOM_DSDT
340 if (strncmp(existing_table->signature, "DSDT", 4) == 0) 407 if (strncmp(existing_table->signature, "DSDT", 4) == 0)
341 *new_table = (struct acpi_table_header *)AmlCode; 408 *new_table = (struct acpi_table_header *)AmlCode;
342 else
343 *new_table = NULL;
344#else
345 *new_table = NULL;
346#endif 409#endif
410#ifdef CONFIG_ACPI_CUSTOM_DSDT_INITRD
411 if ((strncmp(existing_table->signature, "DSDT", 4) == 0) &&
412 !acpi_no_initrd_override) {
413 struct acpi_table_header *initrd_table;
414
415 initrd_table = acpi_find_dsdt_initrd();
416 if (initrd_table)
417 *new_table = initrd_table;
418 }
419#endif
420 if (*new_table != NULL) {
421 printk(KERN_WARNING PREFIX "Override [%4.4s-%8.8s], "
422 "this is unsafe: tainting kernel\n",
423 existing_table->signature,
424 existing_table->oem_table_id);
425 add_taint(TAINT_OVERRIDDEN_ACPI_TABLE);
426 }
347 return AE_OK; 427 return AE_OK;
348} 428}
349 429
430#ifdef CONFIG_ACPI_CUSTOM_DSDT_INITRD
431int __init acpi_no_initrd_override_setup(char *s)
432{
433 acpi_no_initrd_override = 1;
434 return 1;
435}
436__setup("acpi_no_initrd_override", acpi_no_initrd_override_setup);
437#endif
438
350static irqreturn_t acpi_irq(int irq, void *dev_id) 439static irqreturn_t acpi_irq(int irq, void *dev_id)
351{ 440{
352 u32 handled; 441 u32 handled;