iommu/vt-d: Parse ANDD records
authorDavid Woodhouse <David.Woodhouse@intel.com>
Fri, 7 Mar 2014 14:34:38 +0000 (14:34 +0000)
committerDavid Woodhouse <David.Woodhouse@intel.com>
Thu, 20 Mar 2014 14:25:23 +0000 (14:25 +0000)
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
drivers/iommu/dmar.c

index b19f9f4c35847f3ea8a7947591de861af8c348f9..eb95020c2314c78b0826382e0ac3e08aaeb2cf22 100644 (file)
@@ -373,6 +373,26 @@ static void dmar_free_drhd(struct dmar_drhd_unit *dmaru)
        kfree(dmaru);
 }
 
+static int __init dmar_parse_one_andd(struct acpi_dmar_header *header)
+{
+       struct acpi_dmar_andd *andd = (void *)header;
+
+       /* Check for NUL termination within the designated length */
+       if (strnlen(andd->object_name, header->length - 8) == header->length - 8) {
+               WARN_TAINT(1, TAINT_FIRMWARE_WORKAROUND,
+                          "Your BIOS is broken; ANDD object name is not NUL-terminated\n"
+                          "BIOS vendor: %s; Ver: %s; Product Version: %s\n",
+                          dmi_get_system_info(DMI_BIOS_VENDOR),
+                          dmi_get_system_info(DMI_BIOS_VERSION),
+                          dmi_get_system_info(DMI_PRODUCT_VERSION));
+               return -EINVAL;
+       }
+       pr_info("ANDD device: %x name: %s\n", andd->device_number,
+               andd->object_name);
+
+       return 0;
+}
+
 #ifdef CONFIG_ACPI_NUMA
 static int __init
 dmar_parse_one_rhsa(struct acpi_dmar_header *header)
@@ -436,6 +456,10 @@ dmar_table_print_dmar_entry(struct acpi_dmar_header *header)
                       (unsigned long long)rhsa->base_address,
                       rhsa->proximity_domain);
                break;
+       case ACPI_DMAR_TYPE_ANDD:
+               /* We don't print this here because we need to sanity-check
+                  it first. So print it in dmar_parse_one_andd() instead. */
+               break;
        }
 }
 
@@ -521,6 +545,9 @@ parse_dmar_table(void)
                        ret = dmar_parse_one_rhsa(entry_header);
 #endif
                        break;
+               case ACPI_DMAR_TYPE_ANDD:
+                       ret = dmar_parse_one_andd(entry_header);
+                       break;
                default:
                        pr_warn("Unknown DMAR structure type %d\n",
                                entry_header->type);