// vim: ft=c #include #include "multiboot.c" #include #include #define MAGIC 0x36D76289 struct tag_st { uint32_t type; uint32_t size; uint8_t data[]; }__attribute__((packed)); struct header { uint32_t size; uint32_t _; }__attribute__((packed)); struct tag_st *generate_tag(uint32_t type, void *data, uint32_t data_size) { struct tag_st *tag = calloc(1, sizeof(struct tag_st) + data_size); tag->type = type; tag->size = sizeof(struct tag_st) + data_size; if(data_size) memcpy(tag->data, data, data_size); return tag; } #define padded_size(tag) (tag->size + ((tag->size%8)?(8-(tag->size%8)):0)) struct header *generate_taglist(int num, ...) { va_list args; va_start(args, num); uint32_t total_size = sizeof(struct header); struct tag_st **tags = calloc(num, sizeof(struct tag_st *)); for(int i = 0; i < num; i++) { tags[i] = va_arg(args, struct tag_st *); total_size += padded_size(tags[i]); } struct header *taglist = calloc(1, total_size); taglist->size = total_size; int pos = 8; uint8_t *p = (uint8_t *)taglist; for(int i = 0; i < num; i++) { memcpy(&p[pos], tags[i], tags[i]->size); pos += padded_size(tags[i]); free(tags[i]); } va_end(args); return taglist; } TEST(correctly_identifies_multiboot2_magic) { uint32_t tags[] = {16, 0, 0, 8}; multiboot_init(MAGIC, tags); ASSERT_EQ_INT(kernel_boot_data.multiboot_version, 2); } TEST(reads_boot_loader_name) { char *name = "ttest"; void *tags = generate_taglist(2, generate_tag(2, name, strlen(name) + 1), generate_tag(0,0,0)); multiboot_init(MAGIC, tags); ASSERT_EQ_STR(kernel_boot_data.bootloader, name, strlen(name)); free(tags); } TEST(reads_kernel_commandline) { char *cmd = "mittos64-kern boot"; void *tags = generate_taglist(2, generate_tag(1, cmd, strlen(cmd) + 1), generate_tag(0,0,0)); multiboot_init(MAGIC, tags); ASSERT_EQ_STR(kernel_boot_data.commandline, cmd, strlen(cmd)); free(tags); } // Here are four very similar tests // The difference is what values are checked and the order of the tags // Their existence is based on experience - helped me actually find a bug TEST(reads_multiple_tags_1) { char *cmd = "mittos64-kern boot"; char *name = "ttest"; void *tags = generate_taglist(3, generate_tag(1, cmd, strlen(cmd) + 1), generate_tag(2, name, strlen(name) + 1), generate_tag(0,0,0) ); multiboot_init(MAGIC, tags); ASSERT_EQ_STR(kernel_boot_data.commandline, cmd, strlen(cmd)); free(tags); } TEST(reads_multiple_tags_2) { char *cmd = "mittos64-kern boot"; char *name = "ttest"; void *tags = generate_taglist(3, generate_tag(1, cmd, strlen(cmd) + 1), generate_tag(2, name, strlen(name) + 1), generate_tag(0,0,0) ); multiboot_init(MAGIC, tags); ASSERT_EQ_STR(kernel_boot_data.bootloader, name, strlen(name)); free(tags); } TEST(reads_multiple_tags_3) { char *cmd = "mittos64-kern boot"; char *name = "ttest"; void *tags = generate_taglist(3, generate_tag(2, name, strlen(name) + 1), generate_tag(1, cmd, strlen(cmd) + 1), generate_tag(0,0,0) ); multiboot_init(MAGIC, tags); ASSERT_EQ_STR(kernel_boot_data.commandline, cmd, strlen(cmd)); free(tags); } TEST(reads_multiple_tags_4) { char *cmd = "mittos64-kern boot"; char *name = "ttest"; void *tags = generate_taglist(3, generate_tag(2, name, strlen(name) + 1), generate_tag(1, cmd, strlen(cmd) + 1), generate_tag(0,0,0) ); multiboot_init(MAGIC, tags); ASSERT_EQ_STR(kernel_boot_data.bootloader, name, strlen(name)); free(tags); } TEST(reads_mmap_tag) { uint32_t mmap[] = {24, 0, 0x90ABCDEF, 0x12345678, 0x00010000, 0x00000000, 0x1, 0x0 }; void *tags = generate_taglist(2, generate_tag(6, mmap, 32), generate_tag(0,0,0) ); multiboot_init(MAGIC, tags); ASSERT_EQ_INT(kernel_boot_data.mmap_size, 1); free(tags); } void setup_memory_areas() { uint32_t mmap[] = {24, 0, 0x90ABCDEF, 0x12345678, 0x00010000, 0x00000000, 0x1, 0x0, 0x0ABCDEF1, 0x23456789, 0x00010000, 0x00000000, 0x1, 0x0 }; void *tags = generate_taglist(2, generate_tag(6, mmap, 56), generate_tag(0,0,0) ); multiboot_init(MAGIC, tags); } TEST(reads_multiple_mmap_tags) { setup_memory_areas(); ASSERT_EQ_INT(kernel_boot_data.mmap_size, 2); } TEST(returns_memory_area_start) { setup_memory_areas(); uintptr_t start, end; uint32_t type; multiboot_get_memory_area(0, &start, &end, &type); ASSERT_EQ_PTR(start, 0x1234567890ABCDEF); } TEST(returns_memory_area_end) { setup_memory_areas(); uintptr_t start, end; uint32_t type; multiboot_get_memory_area(0, &start, &end, &type); ASSERT_EQ_PTR(end, 0x1234567890ACCDEF); } TEST(returns_memory_area_type) { setup_memory_areas(); uintptr_t start, end; uint32_t type; multiboot_get_memory_area(0, &start, &end, &type); ASSERT_EQ_INT(type, 1); } TEST(returns_second_memory_area_start) { setup_memory_areas(); uintptr_t start, end; uint32_t type; multiboot_get_memory_area(1, &start, &end, &type); ASSERT_EQ_PTR(start, 0x234567890ABCDEF1); } TEST(does_not_return_too_many_areas) { setup_memory_areas(); uintptr_t start, end; uint32_t type; int retval = multiboot_get_memory_area(2, &start, &end, &type); ASSERT_NEQ_INT(retval, 0); }