[PATCH] acpi: method: Add better _CRS resource checking

IvanHu ivan.hu at canonical.com
Mon Jan 14 09:43:30 UTC 2013


> + *  CRS large resource checks, simple checking
> + */
> +static void method_test_CRS_large_resource_items(
> +	fwts_framework *fw,
> +	const char *name,
> +	const uint8_t *data,
> +	const uint64_t length,
> +	bool *passed,
> +	const char **tag)
> +{
> +	uint64_t min, max, len, gra;
> +	uint8_t tag_item = data[0] & 0x7f;
> +
> +	static const char *types[] = {
> +		"Reserved",
> +		"24-bit Memory Range Descriptor",
> +		"Generic Register Descriptor",
> +		"Reserved",
> +		"Vendor Defined Descriptor",
> +		"32-bit Memory Range Descriptor",
> +		"32-bit Fixed Location Memory Range Descriptor",
> +		"DWORD Address Space Descriptor",
> +		"WORD Address Space Descriptor",
> +		"Extended IRQ Descriptor",
> +		"QWORD Address Space Descriptor",
> +		"Extended Addresss Space Descriptor",
> +		"GPIO Connection Descriptor",
> +		"Reserved",
> +		"Generic Serial Bus Connection Descriptor",
> +		"Reserved",
> +	};
> +
> +	switch (tag_item) {
> +	case 0x1: /* 6.4.3.1 24-Bit Memory Range Descriptor */
> +		method_test_CRS_large_size(fw, name, data, length, 9, 9, passed);
> +		if (!*passed)	/* Too short, abort */
> +			break;
> +		min = method_CRS_val24(&data[4]);
> +		max = method_CRS_val24(&data[6]);
> +		len = method_CRS_val16(&data[10]);
> +		if (max < min) {
> +			fwts_failed(fw, LOG_LEVEL_MEDIUM,
> +				"Method_CRS24BitMemRangeMaxLessThanMin",
> +				"%s 24-Bit Memory Range Descriptor minimum "
> +				"address range 0x%" PRIx64 " is greater than "
> +				"the maximum address range 0x%" PRIx64 ".",
> +				name, min, max);
> +			*passed = false;
> +		}
> +		if (len > max + 1 - min) {
> +			fwts_failed(fw, LOG_LEVEL_MEDIUM,
> +				"Method_CRS24BitMemRangeLengthTooLarge",
> +				"%s 24-Bit Memory Range Descriptor length "
> +				"0x%" PRIx64 " is greater than size between the "
> +				"the minimum and maximum address ranges "
> +				"0x%" PRIx64 "-0x%" PRIx64 ".",
> +				name, len, min, max);
> +			*passed = false;
> +		}
> +		break;
> +	case 0x2: /* 6.4.3.7 Generic Register Descriptor */
> +		method_test_CRS_large_size(fw, name, data, length, 12, 12, passed);
> +		if (!*passed)
> +			break;
> +		switch (data[3]) {
> +		case 0x00 ... 0x04:
> +		case 0x0a:
> +		case 0x7f:
> +			/* Valid values */
> +			break;
> +		default:
> +			fwts_failed(fw, LOG_LEVEL_HIGH,
> +				"Method_CRSGenericRegAddrSpaceIdInvalid",
> +				"%s Generic Register Descriptor has an invalid "
> +				"Address Space ID 0x%" PRIx8 ".",
> +				name, data[3]);
> +			*passed = false;
> +		}
> +		if (data[6] > 4) {
> +			fwts_failed(fw, LOG_LEVEL_HIGH,
> +				"Method_CRSGenericRegAddrSizeInvalid",
> +				"%s Generic Register Descriptor has an invalid "
> +				"Address Access Size 0x%" PRIx8 ".",
> +				name, data[6]);
> +			*passed = false;
> +		}
> +		break;
> +	case 0x4: /* 6.4.3.2 Vendor-Defined Descriptor */
> +		method_test_CRS_large_size(fw, name, data, length, 0, 65535, passed);
> +		break;
> +	case 0x5: /* 6.4.3.3 32-Bit Memory Range Descriptor */
> +		method_test_CRS_large_size(fw, name, data, length, 17, 17, passed);
> +		if (!*passed)
> +			break;
> +		min = method_CRS_val32(&data[4]);
> +		max = method_CRS_val32(&data[8]);
> +		len = method_CRS_val32(&data[16]);
> +		if (max < min) {
> +			fwts_failed(fw, LOG_LEVEL_MEDIUM,
> +				"Method_CRS32BitMemRangeMaxLessThanMin",
> +				"%s 32-Bit Memory Range Descriptor minimum "
> +				"address range 0x%" PRIx64 " is greater than "
> +				"the maximum address range 0x%" PRIx64 ".",
> +				name, min, max);
> +			*passed = false;
> +		}
> +		if (len > max + 1 - min) {
> +			fwts_failed(fw, LOG_LEVEL_MEDIUM,
> +				"Method_CRS32BitMemRangeLengthTooLarge",
> +				"%s 32-Bit Memory Range Descriptor length "
> +				"0x%" PRIx64 " is greater than size between the "
> +				"the minimum and maximum address ranges "
> +				"0x%" PRIx64 "-0x%" PRIx64 ".",
> +				name, len, min, max);
> +			*passed = false;
> +		}
> +		break;
> +	case 0x6: /* 6.4.3.4 32-Bit Fixed Memory Range Descriptor */
> +		method_test_CRS_large_size(fw, name, data, length, 9, 9, passed);
> +		/* Not much can be checked for this descriptor */
> +		break;
> +	case 0x7: /* 6.4.3.5.2 DWord Address Space Descriptor */
> +		method_test_CRS_large_size(fw, name, data, length, 23, 65535, passed);
> +		if (!*passed)	/* Too short, abort */
> +			break;
> +		gra = method_CRS_val32(&data[6]);
> +		min = method_CRS_val32(&data[10]);
> +		max = method_CRS_val32(&data[14]);
> +		len = method_CRS_val32(&data[22]);
> +
> +		method_test_CRS_mif_maf(fw, name, data[4],
> +			min, max, len, gra,
> +			"64BitDWordAddrSpace",
> +			types[0x7], passed);
> +		break;
> +	case 0x8: /* 6.4.3.5.3 Word Address Space Descriptor */
> +		method_test_CRS_large_size(fw, name, data, length, 13, 65535, passed);
> +		if (!*passed)	/* Too short, abort */
> +			break;
> +		gra = method_CRS_val16(&data[6]);
> +		min = method_CRS_val16(&data[8]);
> +		max = method_CRS_val16(&data[10]);
> +		len = method_CRS_val16(&data[14]);
> +
> +		method_test_CRS_mif_maf(fw, name, data[4],
> +			min, max, len, gra,
> +			"64BitWordAddrSpace",
> +			types[0x8], passed);
> +		break;
> +	case 0x9: /* 6.4.3.6 Extended Interrupt Descriptor */
> +		method_test_CRS_large_size(fw, name, data, length, 6, 65535, passed);
> +		/* Not much can be checked for this descriptor */
> +		break;
> +	case 0xa: /* 6.4.3.5.1 QWord Address Space Descriptor */
> +		method_test_CRS_large_size(fw, name, data, length, 43, 65535, passed);
> +		if (!*passed)	/* Too short, abort */
> +			break;
> +		gra = method_CRS_val64(&data[6]);
> +		min = method_CRS_val64(&data[14]);
> +		max = method_CRS_val64(&data[22]);
> +		len = method_CRS_val64(&data[38]);
> +
> +		method_test_CRS_mif_maf(fw, name, data[4],
> +			min, max, len, gra,
> +			"64BitQWordAddrSpace",
> +			types[0xa], passed);
> +		break;
> +	case 0xb: /* 6.4.3.5.4 Extended Address Space Descriptor */
> +		method_test_CRS_large_size(fw, name, data, length, 53, 53, passed);
> +		if (!*passed)	/* Too short, abort */
> +			break;
> +		gra = method_CRS_val64(&data[8]);
> +		min = method_CRS_val64(&data[16]);
> +		max = method_CRS_val64(&data[24]);
> +		len = method_CRS_val64(&data[40]);
> +
> +		method_test_CRS_mif_maf(fw, name, data[4],
> +			min, max, len, gra,
> +			"64BitExtAddrSpace",
> +			types[0xb], passed);
> +		break;
> +	case 0xc: /* 6.4.3.8.1 GPIO Connection Descriptor */
> +		method_test_CRS_large_size(fw, name, data, length, 22, 65535, passed);
> +		if (!*passed)	/* Too short, abort */
> +			break;
> +		if (data[2] > 2) {

Checking the spec ACPI5.0 p.335, seems that byte 4 is the GPIO 
Connection Type, please help to double-check that. thanks!

> +			fwts_failed(fw, LOG_LEVEL_MEDIUM,
> +				"Method_CRSGpioConnTypeInvalid",
> +				"%s GPIO Connection Descriptor has an invalid "
> +				"Connection Type 0x%" PRIx8 ".",
> +				name, data[2]);
> +				*passed = false;
> +			fwts_advice(fw,
> +				"The GPIO pin connection type is "
> +				"not recognised. It should be either "
> +				"0x00 (interrupt connection) or "
> +				"0x01 (I/O connection). See table "
> +				"6-189 in section 6.4.3.8.1 of the ACPI "
> +                                "specification.");
> +		}
> +		if ((data[9] > 0x03) && (data[9] < 0x80)) {
> +			fwts_failed(fw, LOG_LEVEL_LOW,
> +				"Method_CRSGpioConnTypeInvalid",
> +				"%s GPIO Connection Descriptor has an invalid "
> +				"Pin Configuration Type 0x%" PRIx8 ".",
> +				name, data[9]);
> +				*passed = false;
> +			fwts_advice(fw,
> +				"The GPIO pin configuration type "
> +				"is not recognised. It should be one of:"
> +				"0x00 (default), 0x01 (pull-up), "
> +				"0x02 (pull-down), 0x03 (no-pull), "
> +				"0x80-0xff (vendor defined). See table "
> +				"6-189 in section 6.4.3.8.1 of the ACPI "
> +				"specification.");
> +		}
> +		break;





More information about the fwts-devel mailing list