Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 81e242d0 authored by Len Brown's avatar Len Brown
Browse files

Merge branches 'release' and 'dsdt-override' into release

parents a733a5da 04d94886
Loading
Loading
Loading
Loading
+15 −0
Original line number Diff line number Diff line
Linux supports two methods of overriding the BIOS DSDT:

CONFIG_ACPI_CUSTOM_DSDT builds the image into the kernel.

CONFIG_ACPI_CUSTOM_DSDT_INITRD adds the image to the initrd.

When to use these methods is described in detail on the
Linux/ACPI home page:
http://www.lesswatts.org/projects/acpi/overridingDSDT.php

Note that if both options are used, the DSDT supplied
by the INITRD method takes precedence.

Documentation/initramfs-add-dsdt.sh is provided for convenience
for use with the CONFIG_ACPI_CUSTOM_DSDT_INITRD method.
+43 −0
Original line number Diff line number Diff line
#!/bin/bash
# Adds a DSDT file to the initrd (if it's an initramfs)
# first argument is the name of archive
# second argument is the name of the file to add
# The file will be copied as /DSDT.aml

# 20060126: fix "Premature end of file" with some old cpio (Roland Robic)
# 20060205: this time it should really work

# check the arguments
if [ $# -ne 2 ]; then
	program_name=$(basename $0)
	echo "\
$program_name: too few arguments
Usage: $program_name initrd-name.img DSDT-to-add.aml
Adds a DSDT file to an initrd (in initramfs format)

  initrd-name.img: filename of the initrd in initramfs format
  DSDT-to-add.aml: filename of the DSDT file to add
  " 1>&2
    exit 1
fi

# we should check it's an initramfs

tempcpio=$(mktemp -d)
# cleanup on exit, hangup, interrupt, quit, termination
trap 'rm -rf $tempcpio' 0 1 2 3 15

# extract the archive
gunzip -c "$1" > "$tempcpio"/initramfs.cpio || exit 1

# copy the DSDT file at the root of the directory so that we can call it "/DSDT.aml"
cp -f "$2" "$tempcpio"/DSDT.aml

# add the file
cd "$tempcpio"
(echo DSDT.aml | cpio --quiet -H newc -o -A -O "$tempcpio"/initramfs.cpio) || exit 1
cd "$OLDPWD"

# re-compress the archive
gzip -c "$tempcpio"/initramfs.cpio > "$1"
+3 −0
Original line number Diff line number Diff line
@@ -177,6 +177,9 @@ and is between 256 and 4096 characters. It is defined in the file

	acpi_no_auto_ssdt	[HW,ACPI] Disable automatic loading of SSDT

	acpi_no_initrd_override	[KNL,ACPI]
			Disable loading custom ACPI tables from the initramfs

	acpi_os_name=	[HW,ACPI] Tell ACPI BIOS the name of the OS
			Format: To spoof as Windows 98: ="Microsoft Windows"

+15 −2
Original line number Diff line number Diff line
@@ -276,8 +276,10 @@ config ACPI_CUSTOM_DSDT
	depends on !STANDALONE
	default n 
	help
	  This option is to load a custom ACPI DSDT
	  If you don't know what that is, say N.
	  This option supports a custom DSDT by linking it into the kernel.
	  See Documentation/acpi/dsdt-override.txt

	  If unsure, say N.

config ACPI_CUSTOM_DSDT_FILE
	string "Custom DSDT Table file to include"
@@ -287,6 +289,17 @@ 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
	  This option supports a custom DSDT by optionally loading it from initrd.
	  See Documentation/acpi/dsdt-override.txt

	  If you are not using this feature now, but may use it 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
+93 −4
Original line number Diff line number Diff line
@@ -91,6 +91,10 @@ static DEFINE_SPINLOCK(acpi_res_lock);
#define	OSI_STRING_LENGTH_MAX 64	/* arbitrary */
static char osi_additional_string[OSI_STRING_LENGTH_MAX];

#ifdef CONFIG_ACPI_CUSTOM_DSDT_INITRD
static int acpi_no_initrd_override;
#endif

/*
 * "Ode to _OSI(Linux)"
 *
@@ -329,6 +333,67 @@ 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 "Checking initramfs for custom DSDT");

	/*
	 * 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.
	 * A static/init firmware infrastructure doesn't exist yet...
	 */
	if (vfs_stat(ramfs_dsdt_name, &stat) < 0)
		return ret;

	len = stat.size;
	/* check especially against empty files */
	if (len <= 4) {
		printk(KERN_ERR PREFIX "Failed: DSDT only %lu bytes.\n", len);
		return ret;
	}

	firmware_file = filp_open(ramfs_dsdt_name, O_RDONLY, 0);
	if (IS_ERR(firmware_file)) {
		printk(KERN_ERR PREFIX "Failed to open %s.\n", ramfs_dsdt_name);
		return ret;
	}

	dsdt_buffer = kmalloc(len, GFP_ATOMIC);
	if (!dsdt_buffer) {
		printk(KERN_ERR PREFIX "Failed to allocate %lu bytes.\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(KERN_ERR PREFIX "Failed to read %lu bytes from %s.\n",
			len, ramfs_dsdt_name);
		ACPI_FREE(dsdt_buffer);
		goto err;
	}

	printk(KERN_INFO PREFIX "Found %lu byte DSDT in %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)
@@ -336,17 +401,41 @@ 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) &&
	    !acpi_no_initrd_override) {
		struct acpi_table_header *initrd_table;

		initrd_table = acpi_find_dsdt_initrd();
		if (initrd_table)
			*new_table = initrd_table;
	}
#endif
	if (*new_table != NULL) {
		printk(KERN_WARNING PREFIX "Override [%4.4s-%8.8s], "
			   "this is unsafe: tainting kernel\n",
		       existing_table->signature,
		       existing_table->oem_table_id);
		add_taint(TAINT_OVERRIDDEN_ACPI_TABLE);
	}
	return AE_OK;
}

#ifdef CONFIG_ACPI_CUSTOM_DSDT_INITRD
int __init acpi_no_initrd_override_setup(char *s)
{
	acpi_no_initrd_override = 1;
	return 1;
}
__setup("acpi_no_initrd_override", acpi_no_initrd_override_setup);
#endif

static irqreturn_t acpi_irq(int irq, void *dev_id)
{
	u32 handled;
Loading