mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-30 19:51:31 -04:00
ACPI: basic initramfs DSDT override support
The basics of DSDT from initramfs. In case this option is selected, populate_rootfs() is called a bit earlier to have the initramfs content available during ACPI initialization. This is a very similar path to the one available at http://gaugusch.at/kernel.shtml but with some update in the documentation, default set to No and the change of populate_rootfs() the "Jeff Mahony way" (which avoids reading the initramfs twice). Signed-off-by: Thomas Renninger <[email protected]> Signed-off-by: Eric Piel <[email protected]> Signed-off-by: Len Brown <[email protected]>
This commit is contained in:
parent
488b5ec871
commit
71fc47a9ad
5 changed files with 199 additions and 5 deletions
|
|
@ -274,6 +274,23 @@ config ACPI_CUSTOM_DSDT_FILE
|
|||
Enter the full path name to the file which includes the AmlCode
|
||||
declaration.
|
||||
|
||||
config ACPI_CUSTOM_DSDT_INITRD
|
||||
bool "Read Custom DSDT from initramfs"
|
||||
depends on BLK_DEV_INITRD
|
||||
default n
|
||||
help
|
||||
The DSDT (Differentiated System Description Table) often needs to be
|
||||
overridden because of broken BIOS implementations. If this feature is
|
||||
activated you will be able to provide a customized DSDT by adding it
|
||||
to your initramfs. If your mkinitrd tool does not support this feature
|
||||
a script is provided in the documentation. For more details see
|
||||
<file:Documentation/dsdt-initrd.txt> or <http://gaugusch.at/kernel.shtml>.
|
||||
If there is no table found, it will fall-back to the custom DSDT
|
||||
in-kernel (if activated) or to the DSDT from the BIOS.
|
||||
|
||||
Even if you do not need a new one at the moment, you may want to use a
|
||||
better DSDT later. It is safe to say Y here.
|
||||
|
||||
config ACPI_BLACKLIST_YEAR
|
||||
int "Disable ACPI for systems before Jan 1st this year" if X86_32
|
||||
default 0
|
||||
|
|
|
|||
|
|
@ -312,6 +312,66 @@ acpi_os_predefined_override(const struct acpi_predefined_names *init_val,
|
|||
return AE_OK;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ACPI_CUSTOM_DSDT_INITRD
|
||||
struct acpi_table_header *acpi_find_dsdt_initrd(void)
|
||||
{
|
||||
struct file *firmware_file;
|
||||
mm_segment_t oldfs;
|
||||
unsigned long len, len2;
|
||||
struct acpi_table_header *dsdt_buffer, *ret = NULL;
|
||||
struct kstat stat;
|
||||
char *ramfs_dsdt_name = "/DSDT.aml";
|
||||
|
||||
printk(KERN_INFO PREFIX "Looking for DSDT in initramfs... ");
|
||||
|
||||
/*
|
||||
* Never do this at home, only the user-space is allowed to open a file.
|
||||
* The clean way would be to use the firmware loader. But this code must be run
|
||||
* before there is any userspace available. So we need a static/init firmware
|
||||
* infrastructure, which doesn't exist yet...
|
||||
*/
|
||||
if (vfs_stat(ramfs_dsdt_name, &stat) < 0) {
|
||||
printk("not found.\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
len = stat.size;
|
||||
/* check especially against empty files */
|
||||
if (len <= 4) {
|
||||
printk("error, file is too small: only %lu bytes.\n", len);
|
||||
return ret;
|
||||
}
|
||||
|
||||
firmware_file = filp_open(ramfs_dsdt_name, O_RDONLY, 0);
|
||||
if (IS_ERR(firmware_file)) {
|
||||
printk("error, could not open file %s.\n", ramfs_dsdt_name);
|
||||
return ret;
|
||||
}
|
||||
|
||||
dsdt_buffer = ACPI_ALLOCATE(len);
|
||||
if (!dsdt_buffer) {
|
||||
printk("error when allocating %lu bytes of memory.\n", len);
|
||||
goto err;
|
||||
}
|
||||
|
||||
oldfs = get_fs();
|
||||
set_fs(KERNEL_DS);
|
||||
len2 = vfs_read(firmware_file, (char __user *)dsdt_buffer, len, &firmware_file->f_pos);
|
||||
set_fs(oldfs);
|
||||
if (len2 < len) {
|
||||
printk("error trying to read %lu bytes from %s.\n", len, ramfs_dsdt_name);
|
||||
ACPI_FREE(dsdt_buffer);
|
||||
goto err;
|
||||
}
|
||||
|
||||
printk("successfully read %lu bytes from %s.\n", len, ramfs_dsdt_name);
|
||||
ret = dsdt_buffer;
|
||||
err:
|
||||
filp_close(firmware_file, NULL);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
acpi_status
|
||||
acpi_os_table_override(struct acpi_table_header * existing_table,
|
||||
struct acpi_table_header ** new_table)
|
||||
|
|
@ -319,13 +379,18 @@ acpi_os_table_override(struct acpi_table_header * existing_table,
|
|||
if (!existing_table || !new_table)
|
||||
return AE_BAD_PARAMETER;
|
||||
|
||||
*new_table = NULL;
|
||||
|
||||
#ifdef CONFIG_ACPI_CUSTOM_DSDT
|
||||
if (strncmp(existing_table->signature, "DSDT", 4) == 0)
|
||||
*new_table = (struct acpi_table_header *)AmlCode;
|
||||
else
|
||||
*new_table = NULL;
|
||||
#else
|
||||
*new_table = NULL;
|
||||
#endif
|
||||
#ifdef CONFIG_ACPI_CUSTOM_DSDT_INITRD
|
||||
if (strncmp(existing_table->signature, "DSDT", 4) == 0) {
|
||||
struct acpi_table_header *initrd_table = acpi_find_dsdt_initrd();
|
||||
if (initrd_table)
|
||||
*new_table = initrd_table;
|
||||
}
|
||||
#endif
|
||||
return AE_OK;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue