diff --git a/repos/os/src/app/pci_decode/main.cc b/repos/os/src/app/pci_decode/main.cc index c77be1054e..f50e0fba6b 100644 --- a/repos/os/src/app/pci_decode/main.cc +++ b/repos/os/src/app/pci_decode/main.cc @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -52,6 +53,7 @@ struct Main void parse_irq_override_rules(Xml_node & xml); void parse_pci_config_spaces(Xml_node & xml, Xml_generator & generator); void parse_acpi_device_info(Xml_node const &xml, Xml_generator & generator); + void parse_tpm2_table(Xml_node const &xml, Xml_generator & gen); template void for_bridge(Pci::bus_t bus, FN const & fn) @@ -298,6 +300,60 @@ static void parse_acpica_info(Xml_node const &xml, Xml_generator &gen) }); } +/* + * Parse the TPM2 ACPI table and report the device if available. + * Only CRB devices are supported at this time. + * + * See the following document for further information: + * https://trustedcomputinggroup.org/wp-content/uploads/TCG_ACPIGeneralSpec_v1p3_r8_pub.pdf + */ +void Main::parse_tpm2_table(Xml_node const &xml, Xml_generator & gen) +{ + enum { + TPM2_TABLE_CRB_ADDRESS_OFFSET = 40, + TPM2_TABLE_CRB_ADDRESS_MASK = (~0xfff), + TPM2_TABLE_START_METHOD_OFFSET = 48, + TPM2_TABLE_START_METHOD_CRB = 7, + TPM2_TABLE_MIN_SIZE = 52UL, + TPM2_DEVICE_IO_MEM_SIZE = 0x1000U, + }; + + addr_t const addr = xml.attribute_value("addr", 0UL); + size_t const size = xml.attribute_value("size", 0UL); + + if ((addr < 1UL) || (size < TPM2_TABLE_MIN_SIZE)) { + error("TPM2 table info invalid"); + return; + } + + Attached_io_mem_dataspace io_mem { env, addr, size }; + char* ptr = io_mem.local_addr(); + + if (memcmp(ptr, "TPM2", 4) != 0) { + error("TPM2 table parse error"); + return; + } + + uint32_t start_method = + *(reinterpret_cast(ptr + TPM2_TABLE_START_METHOD_OFFSET)); + if (start_method != TPM2_TABLE_START_METHOD_CRB) { + warning("Unsupported TPM2 device found"); + return; + } + + addr_t crb_address = + *(reinterpret_cast(ptr + TPM2_TABLE_CRB_ADDRESS_OFFSET)) & + TPM2_TABLE_CRB_ADDRESS_MASK; + + gen.node("device", [&] + { + gen.attribute("name", "tpm2"); + gen.node("io_mem", [&] { + gen.attribute("address", crb_address); + gen.attribute("size", TPM2_DEVICE_IO_MEM_SIZE); + }); + }); +} /* * By now, we do not have the necessary information about non-PCI devices @@ -307,6 +363,16 @@ static void parse_acpica_info(Xml_node const &xml, Xml_generator &gen) */ void Main::parse_acpi_device_info(Xml_node const &xml, Xml_generator & gen) { + using Table_name = String<5>; + + xml.for_each_sub_node("table", [&] (Xml_node &table) { + Table_name name = table.attribute_value("name", Table_name()); + /* only the TPM2 table is supported at this time */ + if (name == "TPM2") { + parse_tpm2_table(table, gen); + } + }); + /* * PS/2 device */