blob: 1ca5befaf27f97cb2c34da29203501163d2d7b0e [file] [log] [blame]
Michael Brown614c3f42022-03-23 14:57:53 +00001/*
2 * Copyright (C) 2022 Michael Brown <mbrown@fensystems.co.uk>.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 * 02110-1301, USA.
18 *
19 * You can also choose to distribute this program under the terms of
20 * the Unmodified Binary Distribution Licence (as given in the file
21 * COPYING.UBDL), provided that you have satisfied its requirements.
22 */
23
24FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25
26/** @file
27 *
28 * ACPI tests
29 *
30 */
31
32/* Forcibly enable assertions */
33#undef NDEBUG
34
35#include <ipxe/acpi.h>
36#include <ipxe/acpimac.h>
37#include <ipxe/if_ether.h>
38#include <ipxe/test.h>
39
40/** An ACPI test table signature */
41union acpi_test_signature {
42 /** String */
43 char str[4];
44 /** Raw value */
45 uint32_t raw;
46};
47
48/** An ACPI test table */
49struct acpi_test_table {
50 /** Signature */
51 union acpi_test_signature signature;
52 /** Table content */
53 const void *data;
54};
55
56/** An ACPI test table set */
57struct acpi_test_tables {
58 /** Tables */
59 struct acpi_test_table **table;
60 /** Number of tables */
61 unsigned int count;
62};
63
64/** An ACPI MAC extraction test */
65struct acpi_mac_test {
66 /** ACPI test table set */
67 struct acpi_test_tables *tables;
68 /** Expected MAC address */
69 uint8_t expected[ETH_ALEN];
70};
71
72/** Define inline data */
73#define DATA(...) { __VA_ARGS__ }
74
75/** Define an ACPI test table */
76#define ACPI_TABLE( name, SIGNATURE, DATA ) \
77 static const uint8_t name ## _data[] = DATA; \
78 static struct acpi_test_table name = { \
79 .signature = { \
80 .str = SIGNATURE, \
81 }, \
82 .data = name ## _data, \
83 }
84
85/** Define an ACPI test table set */
86#define ACPI_TABLES( name, ... ) \
87 static struct acpi_test_table * name ## _table[] = \
88 { __VA_ARGS__ }; \
89 static struct acpi_test_tables name = { \
90 .table = name ## _table, \
91 .count = ( sizeof ( name ## _table ) / \
92 sizeof ( name ## _table[0] ) ), \
93 }
94
95/** Define an ACPI MAC extraction test */
96#define ACPI_MAC( name, TABLES, EXPECTED ) \
97 static struct acpi_mac_test name = { \
98 .tables = TABLES, \
99 .expected = EXPECTED, \
100 }
101
102/** "AMAC" SSDT
103 *
104 * DefinitionBlock ("", "SSDT", 2, "", "", 0x0) {
105 * Scope (\_SB) {
106 * Method (HW00, 0, Serialized) { Return(0) }
107 * Method (AMAC, 0, Serialized) { ToString("_AUXMAC_#525400aabbcc#") }
108 * Method (HW42, 0, Serialized) { Return(42) }
109 * }
110 * }
111 */
112ACPI_TABLE ( amac_ssdt, "SSDT",
113 DATA ( 0x53, 0x53, 0x44, 0x54, 0x5d, 0x00, 0x00, 0x00, 0x02,
114 0x89, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
115 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
116 0x00, 0x49, 0x4e, 0x54, 0x4c, 0x04, 0x06, 0x21, 0x20,
117 0x10, 0x38, 0x5c, 0x5f, 0x53, 0x42, 0x5f, 0x14, 0x08,
118 0x48, 0x57, 0x30, 0x30, 0x08, 0xa4, 0x00, 0x14, 0x1e,
119 0x41, 0x4d, 0x41, 0x43, 0x08, 0x0d, 0x5f, 0x41, 0x55,
120 0x58, 0x4d, 0x41, 0x43, 0x5f, 0x23, 0x35, 0x32, 0x35,
121 0x34, 0x30, 0x30, 0x61, 0x61, 0x62, 0x62, 0x63, 0x63,
122 0x23, 0x00, 0x14, 0x09, 0x48, 0x57, 0x34, 0x32, 0x08,
123 0xa4, 0x0a, 0x2a ) );
124
125/** "AMAC" test tables */
126ACPI_TABLES ( amac_tables, &amac_ssdt );
127
128/** "AMAC" test */
129ACPI_MAC ( amac, &amac_tables,
130 DATA ( 0x52, 0x54, 0x00, 0xaa, 0xbb, 0xcc ) );
131
132/** "MACA" SSDT1 (does not contain AUXMAC) */
133ACPI_TABLE ( maca_ssdt1, "SSDT",
134 DATA ( 0x53, 0x53, 0x44, 0x54, 0x3e, 0x00, 0x00, 0x00, 0x02,
135 0x5f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
136 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
137 0x00, 0x49, 0x4e, 0x54, 0x4c, 0x04, 0x06, 0x21, 0x20,
138 0x10, 0x19, 0x5c, 0x5f, 0x53, 0x42, 0x5f, 0x14, 0x08,
139 0x48, 0x57, 0x30, 0x30, 0x08, 0xa4, 0x00, 0x14, 0x09,
140 0x48, 0x57, 0x34, 0x32, 0x08, 0xa4, 0x0a, 0x2a ) );
141
142/** "MACA" SSDT2 (contains AUXMAC) */
143ACPI_TABLE ( maca_ssdt2, "SSDT",
144 DATA ( 0x53, 0x53, 0x44, 0x54, 0x54, 0x00, 0x00, 0x00, 0x02,
145 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
146 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
147 0x00, 0x49, 0x4e, 0x54, 0x4c, 0x04, 0x06, 0x21, 0x20,
148 0x10, 0x2f, 0x5c, 0x5f, 0x53, 0x42, 0x5f, 0x14, 0x1e,
149 0x4d, 0x41, 0x43, 0x41, 0x08, 0x0d, 0x5f, 0x41, 0x55,
150 0x58, 0x4d, 0x41, 0x43, 0x5f, 0x23, 0x35, 0x32, 0x35,
151 0x34, 0x30, 0x30, 0x31, 0x31, 0x32, 0x32, 0x33, 0x33,
152 0x23, 0x00, 0x14, 0x09, 0x48, 0x57, 0x39, 0x39, 0x08,
153 0xa4, 0x0a, 0x63 ) );
154
155/** "MACA" test tables */
156ACPI_TABLES ( maca_tables, &maca_ssdt1, &maca_ssdt2 );
157
158/** "MACA" test */
159ACPI_MAC ( maca, &maca_tables,
160 DATA ( 0x52, 0x54, 0x00, 0x11, 0x22, 0x33 ) );
161
Michael Brownf58b5102022-03-23 15:02:17 +0000162/** "RTMA" SSDT */
163ACPI_TABLE ( rtma_ssdt, "SSDT",
164 DATA ( 0x53, 0x53, 0x44, 0x54, 0x44, 0x00, 0x00, 0x00, 0x02,
165 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
166 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
167 0x00, 0x49, 0x4e, 0x54, 0x4c, 0x04, 0x06, 0x21, 0x20,
168 0x10, 0x1f, 0x5c, 0x5f, 0x53, 0x42, 0x5f, 0x14, 0x18,
169 0x52, 0x54, 0x4d, 0x41, 0x08, 0x0d, 0x5f, 0x52, 0x54,
170 0x58, 0x4d, 0x41, 0x43, 0x5f, 0x23, 0x52, 0x54, 0x30,
171 0x30, 0x30, 0x31, 0x23, 0x00 ) );
172
173/** "RTMA" test tables */
174ACPI_TABLES ( rtma_tables, &rtma_ssdt );
175
176/** "RTMA" test */
177ACPI_MAC ( rtma, &rtma_tables,
178 DATA ( 0x52, 0x54, 0x30, 0x30, 0x30, 0x31 ) );
179
Michael Brown614c3f42022-03-23 14:57:53 +0000180/** Current ACPI test table set */
181static struct acpi_test_tables *acpi_test_tables;
182
183/**
184 * Locate ACPI test table
185 *
186 * @v signature Requested table signature
187 * @v index Requested index of table with this signature
188 * @ret table Table, or UNULL if not found
189 */
190static userptr_t acpi_test_find ( uint32_t signature, unsigned int index ) {
191 struct acpi_test_table *table;
192 unsigned int i;
193
194 /* Fail if no test tables are installed */
195 if ( ! acpi_test_tables )
196 return UNULL;
197
198 /* Scan through test tables */
199 for ( i = 0 ; i < acpi_test_tables->count ; i++ ) {
200 table = acpi_test_tables->table[i];
201 if ( ( signature == le32_to_cpu ( table->signature.raw ) ) &&
202 ( index-- == 0 ) ) {
203 return virt_to_user ( table->data );
204 }
205 }
206
207 return UNULL;
208}
209
210/** Override ACPI table finder */
211typeof ( acpi_find ) *acpi_finder = acpi_test_find;
212
213/**
214 * Report ACPI MAC extraction test result
215 *
216 * @v test ACPI MAC extraction test
217 * @v file Test code file
218 * @v line Test code line
219 */
220static void acpi_mac_okx ( struct acpi_mac_test *test,
221 const char *file, unsigned int line ) {
222 uint8_t mac[ETH_ALEN];
223 int rc;
224
225 /* Set test table set */
226 acpi_test_tables = test->tables;
227
228 /* Extract MAC address */
229 rc = acpi_mac ( mac );
230 okx ( rc == 0, file, line );
231
232 /* Check extracted MAC address */
233 okx ( memcmp ( mac, test->expected, ETH_ALEN ) == 0, file, line );
234
235 /* Clear test table set */
236 acpi_test_tables = NULL;
237}
238#define acpi_mac_ok( test ) \
239 acpi_mac_okx ( test, __FILE__, __LINE__ )
240
241/**
242 * Perform ACPI self-test
243 *
244 */
245static void acpi_test_exec ( void ) {
246
247 /* MAC extraction tests */
248 acpi_mac_ok ( &amac );
249 acpi_mac_ok ( &maca );
Michael Brownf58b5102022-03-23 15:02:17 +0000250 acpi_mac_ok ( &rtma );
Michael Brown614c3f42022-03-23 14:57:53 +0000251}
252
253/** ACPI self-test */
254struct self_test acpi_test __self_test = {
255 .name = "acpi",
256 .exec = acpi_test_exec,
257};