1 /* SPDX-License-Identifier: GPL-2.0-only */
5 #include <tests/test.h>
6 #include <acpi/acpigen.h>
8 #define ACPIGEN_TEST_BUFFER_SZ (16 * KiB)
10 /* Returns AML package length. Works with normal and extended packages.
11 This implementation is independent from acpigen.c implementation of package length. */
12 static u32
decode_package_length(const char *ptr
)
14 const u8
*aml
= (u8
*)ptr
;
15 const u32 offset
= (aml
[0] == EXT_OP_PREFIX
? 2 : 1);
16 u32 byte_zero_mask
= 0x3F; /* Bits [0:5] */
17 u32 byte_count
= aml
[offset
] >> 6;
18 u32 package_length
= 0;
21 package_length
|= aml
[offset
+ byte_count
] << ((byte_count
<< 3) - 4);
22 byte_zero_mask
= 0x0F; /* Use bits [0:3] of byte 0 */
26 package_length
|= (aml
[offset
] & byte_zero_mask
);
28 return package_length
;
31 static u32
get_current_block_length(const char *base
)
33 const u32 offset
= (base
[0] == EXT_OP_PREFIX
? 2 : 1);
35 return ((uintptr_t)acpigen_get_current() - ((uintptr_t)base
+ offset
));
38 static int setup_acpigen(void **state
)
40 void *buffer
= malloc(ACPIGEN_TEST_BUFFER_SZ
);
45 memset(buffer
, 0, ACPIGEN_TEST_BUFFER_SZ
);
51 static int teardown_acpigen(void **state
)
57 static void test_acpigen_single_if(void **state
)
59 char *acpigen_buf
= *state
;
60 u32 if_package_length
= 0;
63 acpigen_set_current(acpigen_buf
);
65 /* Create dummy AML */
66 acpigen_write_if_lequal_op_int(LOCAL0_OP
, 64);
68 for (int i
= 0; i
< 20; ++i
)
69 acpigen_write_store_ops(ZERO_OP
, LOCAL1_OP
);
74 if_package_length
= decode_package_length(acpigen_buf
);
75 block_length
= get_current_block_length(acpigen_buf
);
76 assert_int_equal(if_package_length
, block_length
);
79 static void create_nested_ifs_recursive(size_t stack_len
[], u32 i
, u32 n
)
84 char *const start
= acpigen_get_current();
85 acpigen_write_if_and(LOCAL0_OP
, ZERO_OP
);
87 for (int k
= 0; k
< 3; ++k
)
88 acpigen_write_store_ops(ZERO_OP
, LOCAL1_OP
);
90 create_nested_ifs_recursive(stack_len
, i
+ 1, n
);
93 stack_len
[i
] = acpigen_get_current() - start
;
96 static void test_acpigen_nested_ifs(void **state
)
98 char *acpigen_buf
= *state
;
99 const size_t nesting_level
= 8;
100 size_t block_len
[8] = {0};
102 acpigen_set_current(acpigen_buf
);
104 create_nested_ifs_recursive(block_len
, 0, nesting_level
);
106 for (int i
= 0, j
= 0; i
< nesting_level
; ++i
, ++j
) {
107 /* Find next if op */
108 for (; j
< ACPIGEN_TEST_BUFFER_SZ
; ++j
) {
109 if ((u8
)acpigen_buf
[j
] == IF_OP
)
112 assert_int_equal(decode_package_length(acpigen_buf
+ j
), block_len
[i
] - 1);
116 static void test_acpigen_write_package(void **state
)
118 char *acpigen_buf
= *state
;
122 acpigen_set_current(acpigen_buf
);
123 acpigen_write_package(3);
125 acpigen_write_return_singleton_buffer(0xA);
126 acpigen_write_return_singleton_buffer(0x7);
127 acpigen_write_return_singleton_buffer(0xF);
131 package_length
= decode_package_length(acpigen_buf
);
132 block_length
= get_current_block_length(acpigen_buf
);
133 assert_int_equal(package_length
, block_length
);
136 static void test_acpigen_scope_with_contents(void **state
)
138 char *acpigen_buf
= *state
;
139 char *block_start
[8] = {0};
140 u32 block_counter
= 0;
144 acpigen_set_current(acpigen_buf
);
146 /* Scope("\_SB") { */
147 block_start
[block_counter
++] = acpigen_get_current();
148 acpigen_write_scope("\\_SB");
150 /* Device("PCI0") { */
151 block_start
[block_counter
++] = acpigen_get_current();
152 acpigen_write_device("PCI0");
154 /* Name(INT1, 0x1234) */
155 acpigen_write_name_integer("INT1", 0x1234);
157 /* Name (_HID, EisaId ("PNP0A08")) // PCI Express Bus */
158 acpigen_write_name("_HID");
159 acpigen_emit_eisaid("PNP0A08");
161 /* Method(^BN00, 0, NotSerialized) { */
162 block_start
[block_counter
++] = acpigen_get_current();
163 acpigen_write_method("^BN00", 0);
165 /* Return( 0x12 + ^PCI0.INT1 ) */
166 acpigen_write_return_op(AND_OP
);
167 acpigen_write_byte(0x12);
168 acpigen_emit_namestring("^PCI0.INT1");
173 package_length
= decode_package_length(block_start
[block_counter
]);
174 block_length
= get_current_block_length(block_start
[block_counter
]);
175 assert_int_equal(package_length
, block_length
);
177 /* Method (_BBN, 0, NotSerialized) { */
178 block_start
[block_counter
++] = acpigen_get_current();
179 acpigen_write_method("_BBN", 0);
181 /* Return (BN00 ()) */
182 acpigen_write_return_namestr("BN00");
183 acpigen_emit_byte(0x0A);
188 package_length
= decode_package_length(block_start
[block_counter
]);
189 block_length
= get_current_block_length(block_start
[block_counter
]);
190 assert_int_equal(package_length
, block_length
);
195 package_length
= decode_package_length(block_start
[block_counter
]);
196 block_length
= get_current_block_length(block_start
[block_counter
]);
197 assert_int_equal(package_length
, block_length
);
202 package_length
= decode_package_length(block_start
[block_counter
]);
203 block_length
= get_current_block_length(block_start
[block_counter
]);
204 assert_int_equal(package_length
, block_length
);
209 const struct CMUnitTest tests
[] = {
210 cmocka_unit_test_setup_teardown(test_acpigen_single_if
, setup_acpigen
,
212 cmocka_unit_test_setup_teardown(test_acpigen_nested_ifs
, setup_acpigen
,
214 cmocka_unit_test_setup_teardown(test_acpigen_write_package
, setup_acpigen
,
216 cmocka_unit_test_setup_teardown(test_acpigen_scope_with_contents
, setup_acpigen
,
220 return cb_run_group_tests(tests
, NULL
, NULL
);