Commit c420dbd1 authored by Thomas Gleixner's avatar Thomas Gleixner Committed by Rafael J. Wysocki
Browse files

ACPI: Implement proper length checks for mem resources



Check whether the resulting length is the same as the given
length. Check for start <= end as well.

We need to hand in the resource for this, so we can apply the flags
directly.

[Jiang] Remove enforcement that resource starting address must be
non-zero.

Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
Signed-off-by: default avatarJiang Liu <jiang.liu@linux.intel.com>
Signed-off-by: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
parent c793504d
Loading
Loading
Loading
Loading
+35 −27
Original line number Diff line number Diff line
@@ -34,21 +34,37 @@
#define valid_IRQ(i) (true)
#endif

static unsigned long acpi_dev_memresource_flags(u64 len, u8 write_protect,
						bool window)
static bool acpi_dev_resource_len_valid(u64 start, u64 end, u64 len, bool io)
{
	unsigned long flags = IORESOURCE_MEM;
	u64 reslen = end - start + 1;

	if (len == 0)
		flags |= IORESOURCE_DISABLED;
	/*
	 * CHECKME: len might be required to check versus a minimum
	 * length as well. 1 for io is fine, but for memory it does
	 * not make any sense at all.
	 */
	if (len && reslen && reslen == len && start <= end)
		return true;

	pr_info("ACPI: invalid or unassigned resource %s [%016llx - %016llx] length [%016llx]\n",
		io ? "io" : "mem", start, end, len);

	return false;
}

static void acpi_dev_memresource_flags(struct resource *res, u64 len,
				       u8 write_protect, bool window)
{
	res->flags = IORESOURCE_MEM;

	if (!acpi_dev_resource_len_valid(res->start, res->end, len, false))
		res->flags |= IORESOURCE_DISABLED;

	if (write_protect == ACPI_READ_WRITE_MEMORY)
		flags |= IORESOURCE_MEM_WRITEABLE;
		res->flags |= IORESOURCE_MEM_WRITEABLE;

	if (window)
		flags |= IORESOURCE_WINDOW;

	return flags;
		res->flags |= IORESOURCE_WINDOW;
}

static void acpi_dev_get_memresource(struct resource *res, u64 start, u64 len,
@@ -56,7 +72,7 @@ static void acpi_dev_get_memresource(struct resource *res, u64 start, u64 len,
{
	res->start = start;
	res->end = start + len - 1;
	res->flags = acpi_dev_memresource_flags(len, write_protect, false);
	acpi_dev_memresource_flags(res, len, write_protect, false);
}

/**
@@ -77,24 +93,18 @@ bool acpi_dev_resource_memory(struct acpi_resource *ares, struct resource *res)
	switch (ares->type) {
	case ACPI_RESOURCE_TYPE_MEMORY24:
		memory24 = &ares->data.memory24;
		if (!memory24->minimum && !memory24->address_length)
			return false;
		acpi_dev_get_memresource(res, memory24->minimum,
					 memory24->address_length,
					 memory24->write_protect);
		break;
	case ACPI_RESOURCE_TYPE_MEMORY32:
		memory32 = &ares->data.memory32;
		if (!memory32->minimum && !memory32->address_length)
			return false;
		acpi_dev_get_memresource(res, memory32->minimum,
					 memory32->address_length,
					 memory32->write_protect);
		break;
	case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
		fixed_memory32 = &ares->data.fixed_memory32;
		if (!fixed_memory32->address && !fixed_memory32->address_length)
			return false;
		acpi_dev_get_memresource(res, fixed_memory32->address,
					 fixed_memory32->address_length,
					 fixed_memory32->write_protect);
@@ -102,7 +112,8 @@ bool acpi_dev_resource_memory(struct acpi_resource *ares, struct resource *res)
	default:
		return false;
	}
	return true;

	return !(res->flags & IORESOURCE_DISABLED);
}
EXPORT_SYMBOL_GPL(acpi_dev_resource_memory);

@@ -186,7 +197,6 @@ bool acpi_dev_resource_address_space(struct acpi_resource *ares,
	acpi_status status;
	struct acpi_resource_address64 addr;
	bool window;
	u64 len;
	u8 io_decode;

	status = acpi_resource_to_address64(ares, &addr);
@@ -199,8 +209,7 @@ bool acpi_dev_resource_address_space(struct acpi_resource *ares,

	switch(addr.resource_type) {
	case ACPI_MEMORY_RANGE:
		len = addr.address.maximum - addr.address.minimum + 1;
		res->flags = acpi_dev_memresource_flags(len,
		acpi_dev_memresource_flags(res, addr.address.address_length,
					   addr.info.mem.write_protect,
					   window);
		break;
@@ -236,7 +245,6 @@ bool acpi_dev_resource_ext_address_space(struct acpi_resource *ares,
{
	struct acpi_resource_extended_address64 *ext_addr;
	bool window;
	u64 len;
	u8 io_decode;

	if (ares->type != ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64)
@@ -250,8 +258,8 @@ bool acpi_dev_resource_ext_address_space(struct acpi_resource *ares,

	switch(ext_addr->resource_type) {
	case ACPI_MEMORY_RANGE:
		len = ext_addr->address.maximum - ext_addr->address.minimum + 1;
		res->flags = acpi_dev_memresource_flags(len,
		acpi_dev_memresource_flags(res,
					   ext_addr->address.address_length,
					   ext_addr->info.mem.write_protect,
					   window);
		break;