aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/osl.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/acpi/osl.c')
-rw-r--r--drivers/acpi/osl.c73
1 files changed, 69 insertions, 4 deletions
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index e53fb516f9d4..131936e7ff17 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -312,6 +312,66 @@ acpi_os_predefined_override(const struct acpi_predefined_names *init_val,
312 return AE_OK; 312 return AE_OK;
313} 313}
314 314
315#ifdef CONFIG_ACPI_CUSTOM_DSDT_INITRD
316struct acpi_table_header *acpi_find_dsdt_initrd(void)
317{
318 struct file *firmware_file;
319 mm_segment_t oldfs;
320 unsigned long len, len2;
321 struct acpi_table_header *dsdt_buffer, *ret = NULL;
322 struct kstat stat;
323 char *ramfs_dsdt_name = "/DSDT.aml";
324
325 printk(KERN_INFO PREFIX "Looking for DSDT in initramfs... ");
326
327 /*
328 * Never do this at home, only the user-space is allowed to open a file.
329 * The clean way would be to use the firmware loader. But this code must be run
330 * before there is any userspace available. So we need a static/init firmware
331 * infrastructure, which doesn't exist yet...
332 */
333 if (vfs_stat(ramfs_dsdt_name, &stat) < 0) {
334 printk("not found.\n");
335 return ret;
336 }
337
338 len = stat.size;
339 /* check especially against empty files */
340 if (len <= 4) {
341 printk("error, file is too small: only %lu bytes.\n", len);
342 return ret;
343 }
344
345 firmware_file = filp_open(ramfs_dsdt_name, O_RDONLY, 0);
346 if (IS_ERR(firmware_file)) {
347 printk("error, could not open file %s.\n", ramfs_dsdt_name);
348 return ret;
349 }
350
351 dsdt_buffer = ACPI_ALLOCATE(len);
352 if (!dsdt_buffer) {
353 printk("error when allocating %lu bytes of memory.\n", len);
354 goto err;
355 }
356
357 oldfs = get_fs();
358 set_fs(KERNEL_DS);
359 len2 = vfs_read(firmware_file, (char __user *)dsdt_buffer, len, &firmware_file->f_pos);
360 set_fs(oldfs);
361 if (len2 < len) {
362 printk("error trying to read %lu bytes from %s.\n", len, ramfs_dsdt_name);
363 ACPI_FREE(dsdt_buffer);
364 goto err;
365 }
366
367 printk("successfully read %lu bytes from %s.\n", len, ramfs_dsdt_name);
368 ret = dsdt_buffer;
369err:
370 filp_close(firmware_file, NULL);
371 return ret;
372}
373#endif
374
315acpi_status 375acpi_status
316acpi_os_table_override(struct acpi_table_header * existing_table, 376acpi_os_table_override(struct acpi_table_header * existing_table,
317 struct acpi_table_header ** new_table) 377 struct acpi_table_header ** new_table)
@@ -319,13 +379,18 @@ acpi_os_table_override(struct acpi_table_header * existing_table,
319 if (!existing_table || !new_table) 379 if (!existing_table || !new_table)
320 return AE_BAD_PARAMETER; 380 return AE_BAD_PARAMETER;
321 381
382 *new_table = NULL;
383
322#ifdef CONFIG_ACPI_CUSTOM_DSDT 384#ifdef CONFIG_ACPI_CUSTOM_DSDT
323 if (strncmp(existing_table->signature, "DSDT", 4) == 0) 385 if (strncmp(existing_table->signature, "DSDT", 4) == 0)
324 *new_table = (struct acpi_table_header *)AmlCode; 386 *new_table = (struct acpi_table_header *)AmlCode;
325 else 387#endif
326 *new_table = NULL; 388#ifdef CONFIG_ACPI_CUSTOM_DSDT_INITRD
327#else 389 if (strncmp(existing_table->signature, "DSDT", 4) == 0) {
328 *new_table = NULL; 390 struct acpi_table_header *initrd_table = acpi_find_dsdt_initrd();
391 if (initrd_table)
392 *new_table = initrd_table;
393 }
329#endif 394#endif
330 return AE_OK; 395 return AE_OK;
331} 396}