1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
|
/*
* Unit test.
*
* We make heavy use of assertions to ensure that our expectations are
* met regarding the Syslinux library interfaces. If an assert fails we
* keep running the test if possible to try and save as much information
* regarding the failures.
*
* A unit test function should return an error if it failed to setup the
* infrastructure, e.g. malloc() fails. If an assertion fires, that is
* not mean the test infrastructure failed, merely that the test didn't
* pass.
*
* To work around any include path issues due to the unit tests being
* run on the development host we must include all headers with absolute
* paths.
*/
#include "unittest/unittest.h"
#include "unittest/memmap.h"
#include "../zonelist.c"
#include "test-harness.c"
static int refuse_to_alloc_reserved_region(void)
{
struct syslinux_memmap *mmap;
const char *cmdline;
size_t kernel_size;
bool relocatable = false;
size_t alignment = 1;
addr_t base;
int rv = -1;
mmap = syslinux_init_memmap();
if (!mmap)
goto bail;
if (syslinux_add_memmap(&mmap, 0x90000, 0x10000, SMT_RESERVED))
goto bail;
base = 0x90000;
rv = syslinux_memmap_find(mmap, &base, 0x1000, relocatable, alignment,
base, base, 0, 640 * 1024);
syslinux_assert(rv, "Allocated reserved region 0x%x", base);
rv = 0;
bail:
syslinux_free_memmap(mmap);
return rv;
}
static int refuse_to_alloc_above_max_address(void)
{
struct syslinux_memmap *mmap;
addr_t base = 0x100000;
size_t size = 0x1000;
int rv = -1;
mmap = syslinux_init_memmap();
if (!mmap)
goto bail;
if (syslinux_add_memmap(&mmap, base, size, SMT_FREE))
goto bail;
rv = syslinux_memmap_find(mmap, &base, size, false, 16,
base, base, 0, 640 * 1024);
syslinux_assert(!rv, "Failed to find a free region");
syslinux_assert_str(!(base < 0x100000), "Region below min address");
syslinux_assert_str(!(base > 0x100000), "Region above max address");
rv = 0;
bail:
syslinux_free_memmap(mmap);
return rv;
}
static int alloc_region_with_zero_size(void)
{
int rv;
rv = syslinux_memmap_find(NULL, 0, 0, false, 0, 0, 0, 0, 0);
syslinux_assert(!rv, "Should be able to allocate a zero-size region");
return 0;
}
static int refuse_to_relocate_region(void)
{
struct syslinux_memmap *mmap;
addr_t free_base;
size_t free_size;
int rv = -1;
mmap = syslinux_init_memmap();
if (!mmap)
goto bail;
free_base = 0x20000;
free_size = 0x1000000;
if (syslinux_add_memmap(&mmap, free_base, free_size, SMT_FREE))
goto bail;
free_base = 0x10000;
free_size = 0x7000;
rv = syslinux_memmap_find(mmap, &free_base, free_size, false, 1,
0, (addr_t)-1, (addr_t)0, (addr_t)-1);
syslinux_assert(rv, "Relocated region from 0x10000 to 0x%x", free_base);
bail:
syslinux_free_memmap(mmap);
return rv;
}
static int only_relocate_upwards(void)
{
struct syslinux_memmap *mmap;
addr_t base;
int rv = -1;
mmap = syslinux_init_memmap();
if (!mmap)
goto bail;
if (syslinux_add_memmap(&mmap, 0x00010, 0x1000, SMT_FREE))
goto bail;
base = 0x10000;
rv = syslinux_memmap_find(mmap, &base, 16, true, 1, 0, (addr_t)-1,
0x2000, (addr_t)-1);
syslinux_assert(rv, "Should not have found any entry in memmap");
syslinux_assert_str(base >= 0x10000,
"Relocated in wrong direction 0x%x", base);
rv = 0;
bail:
syslinux_free_memmap(mmap);
return rv;
}
static int alloc_in_pxe_region(void)
{
struct syslinux_memmap *mmap;
addr_t base;
int rv = -1;
mmap = syslinux_init_memmap();
if (!mmap)
goto bail;
/* Construct a memmap with a gap where the PXE region usually is */
if (syslinux_add_memmap(&mmap, 0x00000, 0x8f000, SMT_FREE))
goto bail;
if (syslinux_add_memmap(&mmap, 0x100000, 0xf000, SMT_FREE))
goto bail;
base = 0x90000;
rv = syslinux_memmap_find(mmap, &base, 0x1000, false, 16,
0, (addr_t)-1, 0, (addr_t)-1);
syslinux_assert(rv, "Shouldn't have allocated none existent region");
bail:
syslinux_free_memmap(mmap);
return rv;
}
static int demote_free_region_to_terminal(void)
{
enum syslinux_memmap_types type;
struct syslinux_memmap *mmap;
int rv = -1;
struct test_memmap_entry entries[] = {
{ 0x100000, 0x300000, SMT_TERMINAL },
{ 0x400000, 0x300000, SMT_FREE },
{ 0x700000, 0x20000, SMT_FREE },
{ 0x720000, 0x20000, SMT_TERMINAL },
};
mmap = test_build_mmap(entries, array_sz(entries));
if (!mmap)
goto bail;
type = syslinux_memmap_type(mmap, 0x100000, 0x500000);
syslinux_assert_str(type == SMT_TERMINAL,
"Expected SMT_TERMINAL + SMT_FREE region to cause type demotion");
type = syslinux_memmap_type(mmap, 0x700000, 0x40000);
syslinux_assert_str(type == SMT_TERMINAL,
"Expected SMT_FREE + SMT_TERMINAL region to cause type demotion");
type = syslinux_memmap_type(mmap, 0x100000, 0x640000);
syslinux_assert_str(type == SMT_TERMINAL,
"Expected multiple SMT_{FREE,TERMINAL} regions to cause type demotion");
rv = 0;
bail:
syslinux_free_memmap(mmap);
return rv;
}
/*
* Find the highest address given a set of boundary conditions.
*/
static int test_find_highest(void)
{
struct syslinux_memmap *mmap;
addr_t start;
int rv = -1;
struct test_memmap_entry entries[] = {
0x000000, 0x000000, SMT_FREE,
0x090000, 0x002000, SMT_FREE,
0x092000, 0x100000, SMT_RESERVED,
0x192001, 0x000021, SMT_TERMINAL,
};
mmap = test_build_mmap(entries, array_sz(entries));
if (!mmap)
goto bail;
start = 0x90000;
rv = syslinux_memmap_highest(mmap, SMT_FREE, &start, 0x20, 0x192000, 1);
syslinux_assert(!rv, "Failed to find highest SMT_FREE address");
syslinux_assert_str(start == 0x91fe0,
"0x%x incorrect highest address", start);
start = 0x40000;
rv = syslinux_memmap_highest(mmap, SMT_FREE, &start, 0x20, 0x91480, 1);
syslinux_assert(!rv, "Failed to find highest SMT_FREE address");
syslinux_assert_str(start == 0x91460,
"0x%x incorrect highest address", start);
start = 0x90023;
rv = syslinux_memmap_highest(mmap, SMT_FREE, &start, 0x20, 0x90057, 0x10);
syslinux_assert_str(start == 0x90030,
"0x%x incorrectly aligned highest address", start);
start = 0x00000;
rv = syslinux_memmap_highest(mmap, SMT_TERMINAL, &start,
0x7, 0x192300, 0x10);
syslinux_assert_str(start == 0x192010,
"0x%x incorrectly aligned SMT_TERMINAL address", start);
start = 0x192001;
rv = syslinux_memmap_highest(mmap, SMT_RESERVED, &start,
0x400, (addr_t)-1, 1);
syslinux_assert_str(rv && start == 0x192001,
"Unexpectedly succeeded finding invalid region: 0x%x",
start);
start = 0x191fff;
rv = syslinux_memmap_highest(mmap, SMT_RESERVED, &start,
0x800, (addr_t)-1, 1);
syslinux_assert_str(rv && start == 0x191fff,
"Unexpectedly succeeded finding invalid region: 0x%x",
start);
rv = 0;
bail:
syslinux_free_memmap(mmap);
return rv;
}
int main(int argc, char **argv)
{
refuse_to_alloc_reserved_region();
refuse_to_alloc_above_max_address();
alloc_region_with_zero_size();
refuse_to_relocate_region();
only_relocate_upwards();
alloc_in_pxe_region();
demote_free_region_to_terminal();
test_find_highest();
return 0;
}
|