aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatt Fleming <matt.fleming@intel.com>2013-07-26 10:27:57 +0100
committerMatt Fleming <matt.fleming@intel.com>2013-07-26 10:39:01 +0100
commite4fd80fb096858c399b17c308986aaed563b8ca9 (patch)
treedbee0fb21988207c8f450d40a832e0eb4e4b90d5
parentdbf87405a0eb3de617365feae146b0371158feb2 (diff)
downloadsyslinux-e4fd80fb096858c399b17c308986aaed563b8ca9.tar.gz
syslinux-e4fd80fb096858c399b17c308986aaed563b8ca9.tar.xz
syslinux-e4fd80fb096858c399b17c308986aaed563b8ca9.zip
tests: unit test bios_boot_linux()
The constraints for allocating the kernel cmdline buffer under bios are pretty involved and filled with historic rules. Unit test the bios linux loader to ensure we never violate any of them, while at the same time making sure we actually find a usable chunk of memory. This commit is designed to test the changes in commit 77cadda8 ("load_linux: dynamically calculate the cmdline region"). Signed-off-by: Matt Fleming <matt.fleming@intel.com>
-rw-r--r--com32/lib/syslinux/tests/Makefile3
-rw-r--r--com32/lib/syslinux/tests/load_linux.c199
-rw-r--r--tests/unittest/include/suffix_number.h1
-rw-r--r--tests/unittest/include/syslinux/bootrm.h1
-rw-r--r--tests/unittest/include/syslinux/firmware.h1
-rw-r--r--tests/unittest/include/syslinux/linux.h1
-rw-r--r--tests/unittest/include/syslinux/video.h1
7 files changed, 206 insertions, 1 deletions
diff --git a/com32/lib/syslinux/tests/Makefile b/com32/lib/syslinux/tests/Makefile
index 701ac01b..18b40fc5 100644
--- a/com32/lib/syslinux/tests/Makefile
+++ b/com32/lib/syslinux/tests/Makefile
@@ -1,6 +1,6 @@
CFLAGS = -I$(topdir)/tests/unittest/include
-tests = zonelist movebits memscan
+tests = zonelist movebits memscan load_linux
.INTERMEDIATE: $(tests)
all: banner $(tests)
@@ -14,6 +14,7 @@ harness-files = test-harness.c
zonelist: zonelist.c ../zonelist.c $(harness-files)
movebits: movebits.c ../movebits.c $(harness-files)
memscan: memscan.c ../memscan.c
+load_linux: load_linux.c
%: %.c
$(CC) $(CFLAGS) -o $@ $<
diff --git a/com32/lib/syslinux/tests/load_linux.c b/com32/lib/syslinux/tests/load_linux.c
new file mode 100644
index 00000000..ed973841
--- /dev/null
+++ b/com32/lib/syslinux/tests/load_linux.c
@@ -0,0 +1,199 @@
+#include "unittest/unittest.h"
+#include "unittest/memmap.h"
+
+#include "syslinux/bootrm.h"
+#include <string.h>
+
+/*
+ * load_linux.c dependencies.
+ */
+#include "../../suffix_number.c"
+
+static struct firmware __test_firmware;
+struct firmware *firmware = &__test_firmware;
+
+static struct syslinux_memmap *__test_mmap;
+struct syslinux_memmap *syslinux_memory_map(void)
+{
+ return syslinux_dup_memmap(__test_mmap);
+}
+
+void syslinux_force_text_mode(void) { }
+
+static char *__test_cmdline = "this is a test!!";
+static bool __test_called_boot_rm = false;
+static addr_t __test_cmdline_addr;
+
+int syslinux_shuffle_boot_rm(struct syslinux_movelist *fraglist,
+ struct syslinux_memmap *memmap,
+ uint16_t bootflags,
+ struct syslinux_rm_regs *regs)
+{
+ struct syslinux_movelist *moves, *ml;
+ int rv;
+
+ __test_called_boot_rm = true;
+
+ ml = fraglist;
+ while (ml) {
+ addr_t cmdline_addr, last_lowmem_addr;
+
+ if (ml->src != __test_cmdline)
+ continue;
+
+ last_lowmem_addr = __test_cmdline_addr;
+ cmdline_addr = ml->dst;
+ syslinux_assert_str(cmdline_addr == last_lowmem_addr,
+ "cmdline at 0x%x but expected 0x%x",
+ cmdline_addr, last_lowmem_addr);
+
+ syslinux_assert_str(strlen(__test_cmdline) + 1 == ml->len,
+ "cmdline length %d, expected %d", ml->len,
+ strlen(__test_cmdline) + 1);
+ break;
+ }
+
+ moves = NULL;
+ rv = syslinux_compute_movelist(&moves, fraglist, memmap);
+ syslinux_free_movelist(moves);
+
+ syslinux_assert(!rv, "Failed to compute movelist");
+
+ return -1;
+}
+
+#include "../load_linux.c"
+#include "../zonelist.c"
+#include "test-harness.c"
+
+static void __test_setup_kernel(void *buf)
+{
+ struct linux_header *hdr;
+
+ hdr = buf;
+ memset(hdr, 0, sizeof(*hdr));
+
+ /*
+ * Setup the minimum required fields.
+ */
+ hdr->boot_flag = BOOT_MAGIC;
+ hdr->setup_sects = 1;
+ hdr->version = 0x0201;
+}
+
+static inline addr_t __test_calc_cmdline_addr(addr_t addr)
+{
+ size_t len = strlen(__test_cmdline) + 1;
+ return (addr - len) & ~15;
+}
+
+#define KERNEL_BUF_SIZE 1024
+static void *__test_setup(struct test_memmap_entry *entries,
+ size_t nr_entries,
+ addr_t last)
+{
+ struct syslinux_memmap *mmap;
+ void *buf;
+
+ mmap = test_build_mmap(entries, nr_entries);
+ if (!mmap)
+ goto bail;
+
+ buf = malloc(KERNEL_BUF_SIZE);
+ if (!buf)
+ goto bail;
+
+ __test_setup_kernel(buf);
+
+ __test_mmap = mmap;
+ __test_cmdline_addr = __test_calc_cmdline_addr(last);
+
+ return buf;
+
+bail:
+ syslinux_free_memmap(mmap);
+ return NULL;
+}
+
+static void __test_teardown(void *buf)
+{
+ free(buf);
+ syslinux_free_memmap(__test_mmap);
+
+ __test_called_boot_rm = false;
+ __test_cmdline_addr = 0;
+ __test_mmap = NULL;
+}
+
+/*
+ * Make sure that we can relocate the cmdline to a free region of
+ * memory.
+ *
+ * The below memory map is based on one from VMWare.
+ */
+static int test_cmdline_placement(void)
+{
+ struct syslinux_memmap *mmap;
+ addr_t addr;
+ void *buf;
+ int rv;
+
+ struct test_memmap_entry entries[] = {
+ 0x00000000, 0x00092800, SMT_FREE,
+ 0x00092800, 0x0000d800, SMT_RESERVED,
+ 0x000ca000, 0x00002000, SMT_RESERVED,
+ 0x000dc000, 0x00004000, SMT_RESERVED,
+ 0x000e4000, 0x00001c00, SMT_RESERVED,
+ 0x00100000, 0x3fdf0000, SMT_FREE,
+ };
+
+ buf = __test_setup(entries, array_sz(entries), 0x92800);
+ if (!buf)
+ return -1;
+
+ rv = syslinux_boot_linux(buf, KERNEL_BUF_SIZE, NULL, NULL, __test_cmdline);
+
+ syslinux_assert(__test_called_boot_rm,
+ "Failed to invoke syslinux_shuffle_boot_rm()");
+
+ __test_teardown(buf);
+ return 0;
+}
+
+/*
+ * Ensure that the linux loader only uses SMT_TERMINAL regions as a last
+ * resort.
+ */
+static int test_terminal_regions(void)
+{
+ addr_t addr;
+ void *buf;
+ int rv;
+
+ struct test_memmap_entry entries[] = {
+ 0x000000, 0x090000, SMT_RESERVED,
+ 0x090000, 0x000420, SMT_TERMINAL,
+ 0x090420, 0x000400, SMT_FREE,
+ 0x090820, 0x000200, SMT_TERMINAL,
+ };
+
+ buf = __test_setup(entries, array_sz(entries), 0x090820);
+ if (!buf)
+ return -1;
+
+ rv = syslinux_boot_linux(buf, KERNEL_BUF_SIZE, NULL, NULL, __test_cmdline);
+
+ syslinux_assert(__test_called_boot_rm,
+ "Failed to invoke syslinux_shuffle_boot_rm()");
+
+ __test_teardown(buf);
+ return 0;
+}
+
+int main(int argc, char **argv)
+{
+ test_cmdline_placement();
+ test_terminal_regions();
+
+ return 0;
+}
diff --git a/tests/unittest/include/suffix_number.h b/tests/unittest/include/suffix_number.h
new file mode 100644
index 00000000..33883d2c
--- /dev/null
+++ b/tests/unittest/include/suffix_number.h
@@ -0,0 +1 @@
+#include <../../../com32/include/suffix_number.h>
diff --git a/tests/unittest/include/syslinux/bootrm.h b/tests/unittest/include/syslinux/bootrm.h
new file mode 100644
index 00000000..c36d96eb
--- /dev/null
+++ b/tests/unittest/include/syslinux/bootrm.h
@@ -0,0 +1 @@
+#include <../../../com32/include/syslinux/bootrm.h>
diff --git a/tests/unittest/include/syslinux/firmware.h b/tests/unittest/include/syslinux/firmware.h
new file mode 100644
index 00000000..cd3e9b30
--- /dev/null
+++ b/tests/unittest/include/syslinux/firmware.h
@@ -0,0 +1 @@
+#include <../../../com32/include/syslinux/firmware.h>
diff --git a/tests/unittest/include/syslinux/linux.h b/tests/unittest/include/syslinux/linux.h
new file mode 100644
index 00000000..99b85b7c
--- /dev/null
+++ b/tests/unittest/include/syslinux/linux.h
@@ -0,0 +1 @@
+#include <../../../com32/include/syslinux/linux.h>
diff --git a/tests/unittest/include/syslinux/video.h b/tests/unittest/include/syslinux/video.h
new file mode 100644
index 00000000..c019754d
--- /dev/null
+++ b/tests/unittest/include/syslinux/video.h
@@ -0,0 +1 @@
+#include <../../../com32/include/syslinux/video.h>