]>
Commit | Line | Data |
---|---|---|
d799c67a HS |
1 | // SPDX-License-Identifier: GPL-2.0+ |
2 | /* | |
3 | * efi_selftest_variables | |
4 | * | |
5 | * Copyright (c) 2018 Heinrich Schuchardt <xypron.glpk@gmx.de> | |
6 | * | |
d8b2216c HS |
7 | * This unit test checks the runtime services for variables: |
8 | * GetVariable, GetNextVariableName, SetVariable, QueryVariableInfo. | |
d799c67a HS |
9 | */ |
10 | ||
11 | #include <efi_selftest.h> | |
12 | ||
13 | #define EFI_ST_MAX_DATA_SIZE 16 | |
e1089765 | 14 | #define EFI_ST_MAX_VARNAME_SIZE 80 |
d799c67a HS |
15 | |
16 | static struct efi_boot_services *boottime; | |
17 | static struct efi_runtime_services *runtime; | |
0bda81bf | 18 | static const efi_guid_t guid_vendor0 = |
d799c67a HS |
19 | EFI_GUID(0x67029eb5, 0x0af2, 0xf6b1, |
20 | 0xda, 0x53, 0xfc, 0xb5, 0x66, 0xdd, 0x1c, 0xe6); | |
0bda81bf | 21 | static const efi_guid_t guid_vendor1 = |
d799c67a HS |
22 | EFI_GUID(0xff629290, 0x1fc1, 0xd73f, |
23 | 0x8f, 0xb1, 0x32, 0xf9, 0x0c, 0xa0, 0x42, 0xea); | |
24 | ||
25 | /* | |
26 | * Setup unit test. | |
27 | * | |
28 | * @handle handle of the loaded image | |
29 | * @systable system table | |
30 | */ | |
31 | static int setup(const efi_handle_t img_handle, | |
32 | const struct efi_system_table *systable) | |
33 | { | |
34 | boottime = systable->boottime; | |
35 | runtime = systable->runtime; | |
36 | ||
37 | return EFI_ST_SUCCESS; | |
38 | } | |
39 | ||
40 | /* | |
41 | * Execute unit test. | |
42 | */ | |
43 | static int execute(void) | |
44 | { | |
45 | efi_status_t ret; | |
46 | efi_uintn_t len; | |
47 | u32 attr; | |
48 | u8 v[16] = {0x5d, 0xd1, 0x5e, 0x51, 0x5a, 0x05, 0xc7, 0x0c, | |
49 | 0x35, 0x4a, 0xae, 0x87, 0xa5, 0xdf, 0x0f, 0x65,}; | |
fe5bc23f | 50 | u8 data[EFI_ST_MAX_DATA_SIZE]; |
d799c67a HS |
51 | u16 varname[EFI_ST_MAX_VARNAME_SIZE]; |
52 | int flag; | |
53 | efi_guid_t guid; | |
54 | u64 max_storage, rem_storage, max_size; | |
55 | ||
56 | ret = runtime->query_variable_info(EFI_VARIABLE_BOOTSERVICE_ACCESS, | |
57 | &max_storage, &rem_storage, | |
58 | &max_size); | |
59 | if (ret != EFI_SUCCESS) { | |
60 | efi_st_todo("QueryVariableInfo failed\n"); | |
61 | } else if (!max_storage || !rem_storage || !max_size) { | |
62 | efi_st_error("QueryVariableInfo: wrong info\n"); | |
63 | return EFI_ST_FAILURE; | |
64 | } | |
65 | /* Set variable 0 */ | |
156ccbc3 | 66 | ret = runtime->set_variable(u"efi_st_var0", &guid_vendor0, |
d799c67a HS |
67 | EFI_VARIABLE_BOOTSERVICE_ACCESS, |
68 | 3, v + 4); | |
69 | if (ret != EFI_SUCCESS) { | |
70 | efi_st_error("SetVariable failed\n"); | |
71 | return EFI_ST_FAILURE; | |
fe5bc23f IG |
72 | } |
73 | data[3] = 0xff; | |
74 | len = 3; | |
156ccbc3 | 75 | ret = runtime->get_variable(u"efi_st_var0", &guid_vendor0, |
fe5bc23f IG |
76 | &attr, &len, data); |
77 | if (ret != EFI_SUCCESS) { | |
78 | efi_st_error("GetVariable failed\n"); | |
79 | return EFI_ST_FAILURE; | |
80 | } | |
8101dd3d | 81 | if (memcmp(data, v + 4, 3)) { |
fe5bc23f IG |
82 | efi_st_error("GetVariable returned wrong value\n"); |
83 | return EFI_ST_FAILURE; | |
84 | } | |
85 | if (data[3] != 0xff) { | |
86 | efi_st_error("GetVariable wrote past the end of the buffer\n"); | |
87 | return EFI_ST_FAILURE; | |
d799c67a HS |
88 | } |
89 | /* Set variable 1 */ | |
156ccbc3 | 90 | ret = runtime->set_variable(u"efi_st_var1", &guid_vendor1, |
d799c67a HS |
91 | EFI_VARIABLE_BOOTSERVICE_ACCESS, |
92 | 8, v); | |
93 | if (ret != EFI_SUCCESS) { | |
94 | efi_st_error("SetVariable failed\n"); | |
95 | return EFI_ST_FAILURE; | |
96 | } | |
97 | len = EFI_ST_MAX_DATA_SIZE; | |
156ccbc3 | 98 | ret = runtime->get_variable(u"efi_st_var1", &guid_vendor1, |
d799c67a HS |
99 | &attr, &len, data); |
100 | if (ret != EFI_SUCCESS) { | |
101 | efi_st_error("GetVariable failed\n"); | |
102 | return EFI_ST_FAILURE; | |
103 | } | |
104 | if (len != 8) { | |
105 | efi_st_error("GetVariable returned wrong length %u\n", | |
106 | (unsigned int)len); | |
107 | return EFI_ST_FAILURE; | |
108 | } | |
8101dd3d | 109 | if (memcmp(data, v, 8)) { |
d799c67a HS |
110 | efi_st_error("GetVariable returned wrong value\n"); |
111 | return EFI_ST_FAILURE; | |
112 | } | |
113 | /* Append variable 1 */ | |
156ccbc3 | 114 | ret = runtime->set_variable(u"efi_st_var1", &guid_vendor1, |
d799c67a HS |
115 | EFI_VARIABLE_BOOTSERVICE_ACCESS | |
116 | EFI_VARIABLE_APPEND_WRITE, | |
117 | 7, v + 8); | |
118 | if (ret != EFI_SUCCESS) { | |
5a24239c | 119 | efi_st_error("SetVariable(APPEND_WRITE) failed\n"); |
c9dd62f9 HS |
120 | return EFI_ST_FAILURE; |
121 | } | |
122 | len = EFI_ST_MAX_DATA_SIZE; | |
156ccbc3 | 123 | ret = runtime->get_variable(u"efi_st_var1", &guid_vendor1, |
c9dd62f9 HS |
124 | &attr, &len, data); |
125 | if (ret != EFI_SUCCESS) { | |
126 | efi_st_error("GetVariable failed\n"); | |
127 | return EFI_ST_FAILURE; | |
d799c67a | 128 | } |
c9dd62f9 HS |
129 | if (len != 15) |
130 | efi_st_todo("GetVariable returned wrong length %u\n", | |
131 | (unsigned int)len); | |
132 | if (memcmp(data, v, len)) | |
133 | efi_st_todo("GetVariable returned wrong value\n"); | |
5a24239c | 134 | /* Append variable 2 */ |
156ccbc3 | 135 | ret = runtime->set_variable(u"efi_none", &guid_vendor1, |
5a24239c AT |
136 | EFI_VARIABLE_BOOTSERVICE_ACCESS | |
137 | EFI_VARIABLE_APPEND_WRITE, | |
138 | 15, v); | |
c9dd62f9 | 139 | if (ret != EFI_NOT_FOUND) { |
5a24239c | 140 | efi_st_error("SetVariable(APPEND_WRITE) with size 0 to non-existent variable returns wrong code\n"); |
c9dd62f9 HS |
141 | return EFI_ST_FAILURE; |
142 | } | |
d799c67a | 143 | /* Enumerate variables */ |
9ba35e64 HS |
144 | |
145 | ret = runtime->get_next_variable_name(NULL, u"efi_st_var1", &guid); | |
146 | if (ret != EFI_INVALID_PARAMETER) { | |
147 | efi_st_error("GetNextVariableName missing parameter check\n"); | |
148 | return EFI_ST_FAILURE; | |
149 | } | |
150 | ||
151 | len = 24; | |
152 | ret = runtime->get_next_variable_name(&len, NULL, &guid); | |
153 | if (ret != EFI_INVALID_PARAMETER) { | |
154 | efi_st_error("GetNextVariableName missing parameter check\n"); | |
155 | return EFI_ST_FAILURE; | |
156 | } | |
157 | ||
158 | len = 24; | |
159 | ret = runtime->get_next_variable_name(&len, u"efi_st_var1", NULL); | |
160 | if (ret != EFI_INVALID_PARAMETER) { | |
161 | efi_st_error("GetNextVariableName missing parameter check\n"); | |
162 | return EFI_ST_FAILURE; | |
163 | } | |
164 | ||
165 | len = 1; | |
166 | ret = runtime->get_next_variable_name(&len, u"", &guid); | |
167 | if (ret != EFI_INVALID_PARAMETER) { | |
168 | efi_st_error("GetNextVariableName missing parameter check\n"); | |
169 | return EFI_ST_FAILURE; | |
170 | } | |
171 | ||
172 | len = 16; | |
173 | ret = runtime->get_next_variable_name(&len, u"efi_st_var1", &guid); | |
174 | if (ret != EFI_INVALID_PARAMETER) { | |
175 | efi_st_error("GetNextVariableName missing parameter check\n"); | |
176 | return EFI_ST_FAILURE; | |
177 | } | |
178 | ||
d799c67a HS |
179 | boottime->set_mem(&guid, 16, 0); |
180 | *varname = 0; | |
181 | flag = 0; | |
182 | for (;;) { | |
183 | len = EFI_ST_MAX_VARNAME_SIZE; | |
184 | ret = runtime->get_next_variable_name(&len, varname, &guid); | |
185 | if (ret == EFI_NOT_FOUND) | |
186 | break; | |
187 | if (ret != EFI_SUCCESS) { | |
1170fee6 AT |
188 | efi_st_error("GetNextVariableName failed (%u)\n", |
189 | (unsigned int)ret); | |
190 | return EFI_ST_FAILURE; | |
d799c67a | 191 | } |
8101dd3d | 192 | if (!memcmp(&guid, &guid_vendor0, sizeof(efi_guid_t)) && |
e1089765 | 193 | !efi_st_strcmp_16_8(varname, "efi_st_var0")) { |
1170fee6 | 194 | flag |= 1; |
e1089765 HS |
195 | if (len != 24) { |
196 | efi_st_error("GetNextVariableName report wrong length %u, expected 24\n", | |
197 | (unsigned int)len); | |
198 | return EFI_ST_FAILURE; | |
199 | } | |
200 | } | |
8101dd3d | 201 | if (!memcmp(&guid, &guid_vendor1, sizeof(efi_guid_t)) && |
d799c67a HS |
202 | !efi_st_strcmp_16_8(varname, "efi_st_var1")) |
203 | flag |= 2; | |
204 | } | |
1170fee6 AT |
205 | if (flag != 3) { |
206 | efi_st_error( | |
d799c67a | 207 | "GetNextVariableName did not return all variables\n"); |
1170fee6 AT |
208 | return EFI_ST_FAILURE; |
209 | } | |
d799c67a | 210 | /* Delete variable 1 */ |
156ccbc3 | 211 | ret = runtime->set_variable(u"efi_st_var1", &guid_vendor1, |
d799c67a HS |
212 | 0, 0, NULL); |
213 | if (ret != EFI_SUCCESS) { | |
214 | efi_st_error("SetVariable failed\n"); | |
215 | return EFI_ST_FAILURE; | |
216 | } | |
217 | len = EFI_ST_MAX_DATA_SIZE; | |
156ccbc3 | 218 | ret = runtime->get_variable(u"efi_st_var1", &guid_vendor1, |
d799c67a HS |
219 | &attr, &len, data); |
220 | if (ret != EFI_NOT_FOUND) { | |
221 | efi_st_error("Variable was not deleted\n"); | |
222 | return EFI_ST_FAILURE; | |
223 | } | |
224 | /* Delete variable 0 */ | |
156ccbc3 | 225 | ret = runtime->set_variable(u"efi_st_var0", &guid_vendor0, |
d799c67a HS |
226 | 0, 0, NULL); |
227 | if (ret != EFI_SUCCESS) { | |
228 | efi_st_error("SetVariable failed\n"); | |
229 | return EFI_ST_FAILURE; | |
230 | } | |
231 | len = EFI_ST_MAX_DATA_SIZE; | |
156ccbc3 | 232 | ret = runtime->get_variable(u"efi_st_var0", &guid_vendor0, |
d799c67a HS |
233 | &attr, &len, data); |
234 | if (ret != EFI_NOT_FOUND) { | |
235 | efi_st_error("Variable was not deleted\n"); | |
236 | return EFI_ST_FAILURE; | |
237 | } | |
238 | ||
239 | return EFI_ST_SUCCESS; | |
240 | } | |
241 | ||
242 | EFI_UNIT_TEST(variables) = { | |
243 | .name = "variables", | |
244 | .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT, | |
245 | .setup = setup, | |
246 | .execute = execute, | |
247 | }; |