[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