| /* |
| * Copyright (C) 2022 Michael Brown <mbrown@fensystems.co.uk>. |
| * |
| * This program is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU General Public License as |
| * published by the Free Software Foundation; either version 2 of the |
| * License, or any later version. |
| * |
| * This program is distributed in the hope that it will be useful, but |
| * WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| * General Public License for more details. |
| * |
| * You should have received a copy of the GNU General Public License |
| * along with this program; if not, write to the Free Software |
| * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA |
| * 02110-1301, USA. |
| * |
| * You can also choose to distribute this program under the terms of |
| * the Unmodified Binary Distribution Licence (as given in the file |
| * COPYING.UBDL), provided that you have satisfied its requirements. |
| */ |
| |
| FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); |
| |
| /** @file |
| * |
| * ACPI tests |
| * |
| */ |
| |
| /* Forcibly enable assertions */ |
| #undef NDEBUG |
| |
| #include <ipxe/acpi.h> |
| #include <ipxe/acpimac.h> |
| #include <ipxe/if_ether.h> |
| #include <ipxe/test.h> |
| |
| /** An ACPI test table signature */ |
| union acpi_test_signature { |
| /** String */ |
| char str[4]; |
| /** Raw value */ |
| uint32_t raw; |
| }; |
| |
| /** An ACPI test table */ |
| struct acpi_test_table { |
| /** Signature */ |
| union acpi_test_signature signature; |
| /** Table content */ |
| const void *data; |
| }; |
| |
| /** An ACPI test table set */ |
| struct acpi_test_tables { |
| /** Tables */ |
| struct acpi_test_table **table; |
| /** Number of tables */ |
| unsigned int count; |
| }; |
| |
| /** An ACPI MAC extraction test */ |
| struct acpi_mac_test { |
| /** ACPI test table set */ |
| struct acpi_test_tables *tables; |
| /** Expected MAC address */ |
| uint8_t expected[ETH_ALEN]; |
| }; |
| |
| /** Define inline data */ |
| #define DATA(...) { __VA_ARGS__ } |
| |
| /** Define an ACPI test table */ |
| #define ACPI_TABLE( name, SIGNATURE, DATA ) \ |
| static const uint8_t name ## _data[] = DATA; \ |
| static struct acpi_test_table name = { \ |
| .signature = { \ |
| .str = SIGNATURE, \ |
| }, \ |
| .data = name ## _data, \ |
| } |
| |
| /** Define an ACPI test table set */ |
| #define ACPI_TABLES( name, ... ) \ |
| static struct acpi_test_table * name ## _table[] = \ |
| { __VA_ARGS__ }; \ |
| static struct acpi_test_tables name = { \ |
| .table = name ## _table, \ |
| .count = ( sizeof ( name ## _table ) / \ |
| sizeof ( name ## _table[0] ) ), \ |
| } |
| |
| /** Define an ACPI MAC extraction test */ |
| #define ACPI_MAC( name, TABLES, EXPECTED ) \ |
| static struct acpi_mac_test name = { \ |
| .tables = TABLES, \ |
| .expected = EXPECTED, \ |
| } |
| |
| /** "AMAC" SSDT |
| * |
| * DefinitionBlock ("", "SSDT", 2, "", "", 0x0) { |
| * Scope (\_SB) { |
| * Method (HW00, 0, Serialized) { Return(0) } |
| * Method (AMAC, 0, Serialized) { ToString("_AUXMAC_#525400aabbcc#") } |
| * Method (HW42, 0, Serialized) { Return(42) } |
| * } |
| * } |
| */ |
| ACPI_TABLE ( amac_ssdt, "SSDT", |
| DATA ( 0x53, 0x53, 0x44, 0x54, 0x5d, 0x00, 0x00, 0x00, 0x02, |
| 0x89, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x49, 0x4e, 0x54, 0x4c, 0x04, 0x06, 0x21, 0x20, |
| 0x10, 0x38, 0x5c, 0x5f, 0x53, 0x42, 0x5f, 0x14, 0x08, |
| 0x48, 0x57, 0x30, 0x30, 0x08, 0xa4, 0x00, 0x14, 0x1e, |
| 0x41, 0x4d, 0x41, 0x43, 0x08, 0x0d, 0x5f, 0x41, 0x55, |
| 0x58, 0x4d, 0x41, 0x43, 0x5f, 0x23, 0x35, 0x32, 0x35, |
| 0x34, 0x30, 0x30, 0x61, 0x61, 0x62, 0x62, 0x63, 0x63, |
| 0x23, 0x00, 0x14, 0x09, 0x48, 0x57, 0x34, 0x32, 0x08, |
| 0xa4, 0x0a, 0x2a ) ); |
| |
| /** "AMAC" test tables */ |
| ACPI_TABLES ( amac_tables, &amac_ssdt ); |
| |
| /** "AMAC" test */ |
| ACPI_MAC ( amac, &amac_tables, |
| DATA ( 0x52, 0x54, 0x00, 0xaa, 0xbb, 0xcc ) ); |
| |
| /** "MACA" SSDT1 (does not contain AUXMAC) */ |
| ACPI_TABLE ( maca_ssdt1, "SSDT", |
| DATA ( 0x53, 0x53, 0x44, 0x54, 0x3e, 0x00, 0x00, 0x00, 0x02, |
| 0x5f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x49, 0x4e, 0x54, 0x4c, 0x04, 0x06, 0x21, 0x20, |
| 0x10, 0x19, 0x5c, 0x5f, 0x53, 0x42, 0x5f, 0x14, 0x08, |
| 0x48, 0x57, 0x30, 0x30, 0x08, 0xa4, 0x00, 0x14, 0x09, |
| 0x48, 0x57, 0x34, 0x32, 0x08, 0xa4, 0x0a, 0x2a ) ); |
| |
| /** "MACA" SSDT2 (contains AUXMAC) */ |
| ACPI_TABLE ( maca_ssdt2, "SSDT", |
| DATA ( 0x53, 0x53, 0x44, 0x54, 0x54, 0x00, 0x00, 0x00, 0x02, |
| 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x49, 0x4e, 0x54, 0x4c, 0x04, 0x06, 0x21, 0x20, |
| 0x10, 0x2f, 0x5c, 0x5f, 0x53, 0x42, 0x5f, 0x14, 0x1e, |
| 0x4d, 0x41, 0x43, 0x41, 0x08, 0x0d, 0x5f, 0x41, 0x55, |
| 0x58, 0x4d, 0x41, 0x43, 0x5f, 0x23, 0x35, 0x32, 0x35, |
| 0x34, 0x30, 0x30, 0x31, 0x31, 0x32, 0x32, 0x33, 0x33, |
| 0x23, 0x00, 0x14, 0x09, 0x48, 0x57, 0x39, 0x39, 0x08, |
| 0xa4, 0x0a, 0x63 ) ); |
| |
| /** "MACA" test tables */ |
| ACPI_TABLES ( maca_tables, &maca_ssdt1, &maca_ssdt2 ); |
| |
| /** "MACA" test */ |
| ACPI_MAC ( maca, &maca_tables, |
| DATA ( 0x52, 0x54, 0x00, 0x11, 0x22, 0x33 ) ); |
| |
| /** "RTMA" SSDT */ |
| ACPI_TABLE ( rtma_ssdt, "SSDT", |
| DATA ( 0x53, 0x53, 0x44, 0x54, 0x44, 0x00, 0x00, 0x00, 0x02, |
| 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x49, 0x4e, 0x54, 0x4c, 0x04, 0x06, 0x21, 0x20, |
| 0x10, 0x1f, 0x5c, 0x5f, 0x53, 0x42, 0x5f, 0x14, 0x18, |
| 0x52, 0x54, 0x4d, 0x41, 0x08, 0x0d, 0x5f, 0x52, 0x54, |
| 0x58, 0x4d, 0x41, 0x43, 0x5f, 0x23, 0x52, 0x54, 0x30, |
| 0x30, 0x30, 0x31, 0x23, 0x00 ) ); |
| |
| /** "RTMA" test tables */ |
| ACPI_TABLES ( rtma_tables, &rtma_ssdt ); |
| |
| /** "RTMA" test */ |
| ACPI_MAC ( rtma, &rtma_tables, |
| DATA ( 0x52, 0x54, 0x30, 0x30, 0x30, 0x31 ) ); |
| |
| /** Current ACPI test table set */ |
| static struct acpi_test_tables *acpi_test_tables; |
| |
| /** |
| * Locate ACPI test table |
| * |
| * @v signature Requested table signature |
| * @v index Requested index of table with this signature |
| * @ret table Table, or UNULL if not found |
| */ |
| static userptr_t acpi_test_find ( uint32_t signature, unsigned int index ) { |
| struct acpi_test_table *table; |
| unsigned int i; |
| |
| /* Fail if no test tables are installed */ |
| if ( ! acpi_test_tables ) |
| return UNULL; |
| |
| /* Scan through test tables */ |
| for ( i = 0 ; i < acpi_test_tables->count ; i++ ) { |
| table = acpi_test_tables->table[i]; |
| if ( ( signature == le32_to_cpu ( table->signature.raw ) ) && |
| ( index-- == 0 ) ) { |
| return virt_to_user ( table->data ); |
| } |
| } |
| |
| return UNULL; |
| } |
| |
| /** Override ACPI table finder */ |
| typeof ( acpi_find ) *acpi_finder = acpi_test_find; |
| |
| /** |
| * Report ACPI MAC extraction test result |
| * |
| * @v test ACPI MAC extraction test |
| * @v file Test code file |
| * @v line Test code line |
| */ |
| static void acpi_mac_okx ( struct acpi_mac_test *test, |
| const char *file, unsigned int line ) { |
| uint8_t mac[ETH_ALEN]; |
| int rc; |
| |
| /* Set test table set */ |
| acpi_test_tables = test->tables; |
| |
| /* Extract MAC address */ |
| rc = acpi_mac ( mac ); |
| okx ( rc == 0, file, line ); |
| |
| /* Check extracted MAC address */ |
| okx ( memcmp ( mac, test->expected, ETH_ALEN ) == 0, file, line ); |
| |
| /* Clear test table set */ |
| acpi_test_tables = NULL; |
| } |
| #define acpi_mac_ok( test ) \ |
| acpi_mac_okx ( test, __FILE__, __LINE__ ) |
| |
| /** |
| * Perform ACPI self-test |
| * |
| */ |
| static void acpi_test_exec ( void ) { |
| |
| /* MAC extraction tests */ |
| acpi_mac_ok ( &amac ); |
| acpi_mac_ok ( &maca ); |
| acpi_mac_ok ( &rtma ); |
| } |
| |
| /** ACPI self-test */ |
| struct self_test acpi_test __self_test = { |
| .name = "acpi", |
| .exec = acpi_test_exec, |
| }; |