]> Git Repo - qemu.git/blob - tests/hd-geo-test.c
qapi: Plumb in 'boxed' to qapi generator lower levels
[qemu.git] / tests / hd-geo-test.c
1 /*
2  * Hard disk geometry test cases.
3  *
4  * Copyright (c) 2012 Red Hat Inc.
5  *
6  * Authors:
7  *  Markus Armbruster <[email protected]>,
8  *
9  * This work is licensed under the terms of the GNU GPL, version 2 or later.
10  * See the COPYING file in the top-level directory.
11  */
12
13 /*
14  * Covers only IDE and tests only CMOS contents.  Better than nothing.
15  * Improvements welcome.
16  */
17
18 #include "qemu/osdep.h"
19 #include "qemu-common.h"
20 #include "libqtest.h"
21
22 static char *create_test_img(int secs)
23 {
24     char *template = strdup("/tmp/qtest.XXXXXX");
25     int fd, ret;
26
27     fd = mkstemp(template);
28     g_assert(fd >= 0);
29     ret = ftruncate(fd, (off_t)secs * 512);
30     g_assert(ret == 0);
31     close(fd);
32     return template;
33 }
34
35 typedef struct {
36     int cyls, heads, secs, trans;
37 } CHST;
38
39 typedef enum {
40     mbr_blank, mbr_lba, mbr_chs,
41     mbr_last
42 } MBRcontents;
43
44 typedef enum {
45     /* order is relevant */
46     backend_small, backend_large, backend_empty,
47     backend_last
48 } Backend;
49
50 static const int img_secs[backend_last] = {
51     [backend_small] = 61440,
52     [backend_large] = 8388608,
53     [backend_empty] = -1,
54 };
55
56 static const CHST hd_chst[backend_last][mbr_last] = {
57     [backend_small] = {
58         [mbr_blank] = { 60, 16, 63, 0 },
59         [mbr_lba]   = { 60, 16, 63, 2 },
60         [mbr_chs]   = { 60, 16, 63, 0 }
61     },
62     [backend_large] = {
63         [mbr_blank] = { 8322, 16, 63, 1 },
64         [mbr_lba]   = { 8322, 16, 63, 1 },
65         [mbr_chs]   = { 8322, 16, 63, 0 }
66     },
67 };
68
69 static const char *img_file_name[backend_last];
70
71 static const CHST *cur_ide[4];
72
73 static bool is_hd(const CHST *expected_chst)
74 {
75     return expected_chst && expected_chst->cyls;
76 }
77
78 static void test_cmos_byte(int reg, int expected)
79 {
80     enum { cmos_base = 0x70 };
81     int actual;
82
83     outb(cmos_base + 0, reg);
84     actual = inb(cmos_base + 1);
85     g_assert(actual == expected);
86 }
87
88 static void test_cmos_bytes(int reg0, int n, uint8_t expected[])
89 {
90     int i;
91
92     for (i = 0; i < 9; i++) {
93         test_cmos_byte(reg0 + i, expected[i]);
94     }
95 }
96
97 static void test_cmos_disk_data(void)
98 {
99     test_cmos_byte(0x12,
100                    (is_hd(cur_ide[0]) ? 0xf0 : 0) |
101                    (is_hd(cur_ide[1]) ? 0x0f : 0));
102 }
103
104 static void test_cmos_drive_cyl(int reg0, const CHST *expected_chst)
105 {
106     if (is_hd(expected_chst)) {
107         int c = expected_chst->cyls;
108         int h = expected_chst->heads;
109         int s = expected_chst->secs;
110         uint8_t expected_bytes[9] = {
111             c & 0xff, c >> 8, h, 0xff, 0xff, 0xc0 | ((h > 8) << 3),
112             c & 0xff, c >> 8, s
113         };
114         test_cmos_bytes(reg0, 9, expected_bytes);
115     } else {
116         int i;
117
118         for (i = 0; i < 9; i++) {
119             test_cmos_byte(reg0 + i, 0);
120         }
121     }
122 }
123
124 static void test_cmos_drive1(void)
125 {
126     test_cmos_byte(0x19, is_hd(cur_ide[0]) ? 47 : 0);
127     test_cmos_drive_cyl(0x1b, cur_ide[0]);
128 }
129
130 static void test_cmos_drive2(void)
131 {
132     test_cmos_byte(0x1a, is_hd(cur_ide[1]) ? 47 : 0);
133     test_cmos_drive_cyl(0x24, cur_ide[1]);
134 }
135
136 static void test_cmos_disktransflag(void)
137 {
138     int val, i;
139
140     val = 0;
141     for (i = 0; i < ARRAY_SIZE(cur_ide); i++) {
142         if (is_hd(cur_ide[i])) {
143             val |= cur_ide[i]->trans << (2 * i);
144         }
145     }
146     test_cmos_byte(0x39, val);
147 }
148
149 static void test_cmos(void)
150 {
151     test_cmos_disk_data();
152     test_cmos_drive1();
153     test_cmos_drive2();
154     test_cmos_disktransflag();
155 }
156
157 static int append_arg(int argc, char *argv[], int argv_sz, char *arg)
158 {
159     g_assert(argc + 1 < argv_sz);
160     argv[argc++] = arg;
161     argv[argc] = NULL;
162     return argc;
163 }
164
165 static int setup_common(char *argv[], int argv_sz)
166 {
167     memset(cur_ide, 0, sizeof(cur_ide));
168     return append_arg(0, argv, argv_sz,
169                       g_strdup("-nodefaults"));
170 }
171
172 static void setup_mbr(int img_idx, MBRcontents mbr)
173 {
174     static const uint8_t part_lba[16] = {
175         /* chs 0,1,1 (lba 63) to chs 0,127,63 (8001 sectors) */
176         0x80, 1, 1, 0, 6, 127, 63, 0, 63, 0, 0, 0, 0x41, 0x1F, 0, 0,
177     };
178     static const uint8_t part_chs[16] = {
179         /* chs 0,1,1 (lba 63) to chs 7,15,63 (8001 sectors) */
180         0x80, 1, 1, 0, 6,  15, 63, 7, 63, 0, 0, 0, 0x41, 0x1F, 0, 0,
181     };
182     uint8_t buf[512];
183     int fd, ret;
184
185     memset(buf, 0, sizeof(buf));
186
187     if (mbr != mbr_blank) {
188         buf[0x1fe] = 0x55;
189         buf[0x1ff] = 0xAA;
190         memcpy(buf + 0x1BE, mbr == mbr_lba ? part_lba : part_chs, 16);
191     }
192
193     fd = open(img_file_name[img_idx], O_WRONLY);
194     g_assert(fd >= 0);
195     ret = write(fd, buf, sizeof(buf));
196     g_assert(ret == sizeof(buf));
197     close(fd);
198 }
199
200 static int setup_ide(int argc, char *argv[], int argv_sz,
201                      int ide_idx, const char *dev, int img_idx,
202                      MBRcontents mbr, const char *opts)
203 {
204     char *s1, *s2, *s3;
205
206     s1 = g_strdup_printf("-drive id=drive%d,if=%s",
207                          ide_idx, dev ? "none" : "ide");
208     s2 = dev ? g_strdup("") : g_strdup_printf(",index=%d", ide_idx);
209
210     if (img_secs[img_idx] >= 0) {
211         setup_mbr(img_idx, mbr);
212         s3 = g_strdup_printf(",format=raw,file=%s", img_file_name[img_idx]);
213     } else {
214         s3 = g_strdup(",media=cdrom");
215     }
216     argc = append_arg(argc, argv, argv_sz,
217                       g_strdup_printf("%s%s%s%s", s1, s2, s3, opts));
218     g_free(s1);
219     g_free(s2);
220     g_free(s3);
221
222     if (dev) {
223         argc = append_arg(argc, argv, argv_sz,
224                           g_strdup_printf("-device %s,drive=drive%d,"
225                                           "bus=ide.%d,unit=%d",
226                                           dev, ide_idx,
227                                           ide_idx / 2, ide_idx % 2));
228     }
229     return argc;
230 }
231
232 /*
233  * Test case: no IDE devices
234  */
235 static void test_ide_none(void)
236 {
237     char *argv[256];
238
239     setup_common(argv, ARRAY_SIZE(argv));
240     qtest_start(g_strjoinv(" ", argv));
241     test_cmos();
242     qtest_end();
243 }
244
245 static void test_ide_mbr(bool use_device, MBRcontents mbr)
246 {
247     char *argv[256];
248     int argc;
249     Backend i;
250     const char *dev;
251
252     argc = setup_common(argv, ARRAY_SIZE(argv));
253     for (i = 0; i < backend_last; i++) {
254         cur_ide[i] = &hd_chst[i][mbr];
255         dev = use_device ? (is_hd(cur_ide[i]) ? "ide-hd" : "ide-cd") : NULL;
256         argc = setup_ide(argc, argv, ARRAY_SIZE(argv), i, dev, i, mbr, "");
257     }
258     qtest_start(g_strjoinv(" ", argv));
259     test_cmos();
260     qtest_end();
261 }
262
263 /*
264  * Test case: IDE devices (if=ide) with blank MBRs
265  */
266 static void test_ide_drive_mbr_blank(void)
267 {
268     test_ide_mbr(false, mbr_blank);
269 }
270
271 /*
272  * Test case: IDE devices (if=ide) with MBRs indicating LBA is in use
273  */
274 static void test_ide_drive_mbr_lba(void)
275 {
276     test_ide_mbr(false, mbr_lba);
277 }
278
279 /*
280  * Test case: IDE devices (if=ide) with MBRs indicating CHS is in use
281  */
282 static void test_ide_drive_mbr_chs(void)
283 {
284     test_ide_mbr(false, mbr_chs);
285 }
286
287 /*
288  * Test case: IDE devices (if=none) with blank MBRs
289  */
290 static void test_ide_device_mbr_blank(void)
291 {
292     test_ide_mbr(true, mbr_blank);
293 }
294
295 /*
296  * Test case: IDE devices (if=none) with MBRs indicating LBA is in use
297  */
298 static void test_ide_device_mbr_lba(void)
299 {
300     test_ide_mbr(true, mbr_lba);
301 }
302
303 /*
304  * Test case: IDE devices (if=none) with MBRs indicating CHS is in use
305  */
306 static void test_ide_device_mbr_chs(void)
307 {
308     test_ide_mbr(true, mbr_chs);
309 }
310
311 static void test_ide_drive_user(const char *dev, bool trans)
312 {
313     char *argv[256], *opts;
314     int argc;
315     int secs = img_secs[backend_small];
316     const CHST expected_chst = { secs / (4 * 32) , 4, 32, trans };
317
318     argc = setup_common(argv, ARRAY_SIZE(argv));
319     opts = g_strdup_printf("%s,%s%scyls=%d,heads=%d,secs=%d",
320                            dev ?: "",
321                            trans && dev ? "bios-chs-" : "",
322                            trans ? "trans=lba," : "",
323                            expected_chst.cyls, expected_chst.heads,
324                            expected_chst.secs);
325     cur_ide[0] = &expected_chst;
326     argc = setup_ide(argc, argv, ARRAY_SIZE(argv),
327                      0, dev ? opts : NULL, backend_small, mbr_chs,
328                      dev ? "" : opts);
329     g_free(opts);
330     qtest_start(g_strjoinv(" ", argv));
331     test_cmos();
332     qtest_end();
333 }
334
335 /*
336  * Test case: IDE device (if=ide) with explicit CHS
337  */
338 static void test_ide_drive_user_chs(void)
339 {
340     test_ide_drive_user(NULL, false);
341 }
342
343 /*
344  * Test case: IDE device (if=ide) with explicit CHS and translation
345  */
346 static void test_ide_drive_user_chst(void)
347 {
348     test_ide_drive_user(NULL, true);
349 }
350
351 /*
352  * Test case: IDE device (if=none) with explicit CHS
353  */
354 static void test_ide_device_user_chs(void)
355 {
356     test_ide_drive_user("ide-hd", false);
357 }
358
359 /*
360  * Test case: IDE device (if=none) with explicit CHS and translation
361  */
362 static void test_ide_device_user_chst(void)
363 {
364     test_ide_drive_user("ide-hd", true);
365 }
366
367 /*
368  * Test case: IDE devices (if=ide), but use index=0 for CD-ROM
369  */
370 static void test_ide_drive_cd_0(void)
371 {
372     char *argv[256];
373     int argc, ide_idx;
374     Backend i;
375
376     argc = setup_common(argv, ARRAY_SIZE(argv));
377     for (i = 0; i <= backend_empty; i++) {
378         ide_idx = backend_empty - i;
379         cur_ide[ide_idx] = &hd_chst[i][mbr_blank];
380         argc = setup_ide(argc, argv, ARRAY_SIZE(argv),
381                          ide_idx, NULL, i, mbr_blank, "");
382     }
383     qtest_start(g_strjoinv(" ", argv));
384     test_cmos();
385     qtest_end();
386 }
387
388 int main(int argc, char **argv)
389 {
390     Backend i;
391     int ret;
392
393     g_test_init(&argc, &argv, NULL);
394
395     for (i = 0; i < backend_last; i++) {
396         if (img_secs[i] >= 0) {
397             img_file_name[i] = create_test_img(img_secs[i]);
398         } else {
399             img_file_name[i] = NULL;
400         }
401     }
402
403     qtest_add_func("hd-geo/ide/none", test_ide_none);
404     qtest_add_func("hd-geo/ide/drive/mbr/blank", test_ide_drive_mbr_blank);
405     qtest_add_func("hd-geo/ide/drive/mbr/lba", test_ide_drive_mbr_lba);
406     qtest_add_func("hd-geo/ide/drive/mbr/chs", test_ide_drive_mbr_chs);
407     qtest_add_func("hd-geo/ide/drive/user/chs", test_ide_drive_user_chs);
408     qtest_add_func("hd-geo/ide/drive/user/chst", test_ide_drive_user_chst);
409     qtest_add_func("hd-geo/ide/drive/cd_0", test_ide_drive_cd_0);
410     qtest_add_func("hd-geo/ide/device/mbr/blank", test_ide_device_mbr_blank);
411     qtest_add_func("hd-geo/ide/device/mbr/lba", test_ide_device_mbr_lba);
412     qtest_add_func("hd-geo/ide/device/mbr/chs", test_ide_device_mbr_chs);
413     qtest_add_func("hd-geo/ide/device/user/chs", test_ide_device_user_chs);
414     qtest_add_func("hd-geo/ide/device/user/chst", test_ide_device_user_chst);
415
416     ret = g_test_run();
417
418     for (i = 0; i < backend_last; i++) {
419         unlink(img_file_name[i]);
420     }
421
422     return ret;
423 }
This page took 0.046378 seconds and 4 git commands to generate.