1/* 2 * M5 boot image tool. 3 * 4 * Molly: a fish that starts with an "M" and has 5 letters in it. 5 * 6 * This file processes a menu.lst to generate C definitions for the 7 * multiboot structures. It refers to additional object files 8 * which contain the contents of the kernel and modules as blobs of 9 * data. (Generated using objcopy via build_data_files.sh) 10 * 11 * The resulting files are then linked against molly_boot.S, 12 * molly_init.c, and an ELF loader. This results in a single kernel 13 * image that M5 can boot. 14 */ 15 16#include <stdio.h> 17#include <stdlib.h> 18#include <stdint.h> 19#include <stddef.h> 20#include <stdbool.h> 21#include <string.h> 22#include <assert.h> 23#include <ctype.h> 24#include <inttypes.h> 25#include "elf.h" 26 27#define MAX_MODULES 256 28 29static char *kernel_symbol_prefix; 30static char *kernel_cmd_line; 31static char *module_symbol_prefix[MAX_MODULES]; 32static char *module_cmd_line[MAX_MODULES]; 33 34static char *get_symbol_name_prefix(char *original) { 35 char *prefix = "_binary__"; 36 char *r = malloc(strlen(prefix) + strlen(original) + 1); 37 sprintf(r, "%s%s", prefix, original); 38 for (int i = 0; i < strlen(r); i ++) { 39 if (r[i] == '/') { 40 r[i] = '_'; 41 } 42 } 43 return r; 44} 45 46int main(int argc, char *argv[]) 47{ 48 int got_kernel = 0; 49 int n_modules = 0; 50 int n_mmaps = 0; 51 52 if(argc < 3) { 53 printf("Usage: %s <menu.lst> <output.c>\n", argv[0]); 54 return 0; 55 } 56 57 FILE *f = fopen(argv[1], "r"); 58 assert((f != NULL) && "Could not open input file"); 59 60 FILE *o = fopen(argv[2], "w"); 61 assert((o != NULL) && "Could not open output file"); 62 63 // Output initial part of file: include basic types etc. 64 fprintf(o, "#include <assert.h>\n"); 65 fprintf(o, "#include <stdio.h>\n"); 66 fprintf(o, "#include <stdint.h>\n"); 67 fprintf(o, "#include <stddef.h>\n"); 68 fprintf(o, "#include <string.h>\n"); 69 fprintf(o, "#include <barrelfish_kpi/types.h>\n"); 70 fprintf(o, "#include <errors/errno.h>\n"); 71 fprintf(o, "#include <elf/elf.h>\n"); 72 fprintf(o, "#include <multiboot.h>\n"); 73 74 // Process menu.lst, generating definitions 75 char cmd[1024], args[1024], image[1024]; 76 while(!feof(f)) { 77 char line[1024]; 78 79 cmd[0] = args[0] = image[0] = line[0] = '\0'; 80 81 fgets(line, 1024, f); 82 sscanf(line, "%s %s %[^\n]", cmd, image, args); 83 84 if(!strcmp(cmd, "kernel")) { 85 kernel_symbol_prefix = get_symbol_name_prefix(image); 86 kernel_cmd_line = malloc(strlen(line) + 1); 87 sprintf(kernel_cmd_line, "%s %s", image, args); 88 fprintf(o, "extern char %s_start;\n", kernel_symbol_prefix); 89 fprintf(o, "extern char %s_end;\n", kernel_symbol_prefix); 90 got_kernel = 1; 91 } else if(!strcmp(cmd, "module")) { 92 assert(n_modules < MAX_MODULES); 93 module_symbol_prefix[n_modules] = get_symbol_name_prefix(image); 94 module_cmd_line[n_modules] = malloc(strlen(line) + 1); 95 sprintf(module_cmd_line[n_modules], "%s %s", image, args); 96 fprintf(o, "extern char %s_start;\n", module_symbol_prefix[n_modules]); 97 fprintf(o, "extern char %s_end;\n", module_symbol_prefix[n_modules]); 98 n_modules ++; 99 } else if(!strcmp(cmd, "mmap")) { 100 uint64_t base, len; 101 int type; 102 sscanf(args, "%" SCNi64 " %" SCNi64 " %i", 103 &base, &len, &type); 104 printf("Inserting MMAP %d: [0x%" PRIx64 ", 0x%" PRIx64 "], type %d\n", 105 n_mmaps, base, len, type); 106 fprintf(o, "static uint64_t mbi_mmap%d[] = {0x%llx, 0x%llx, %d};\n", 107 n_mmaps, base, len, type); 108 n_mmaps ++; 109 } else { 110 bool iscmd = false; 111 for(int i = 0; i < strlen(cmd); i++) { 112 if(cmd[i] == '#') { 113 break; 114 } 115 if(!isspace(cmd[i])) { 116 iscmd = true; 117 break; 118 } 119 } 120 if(iscmd) { 121 printf("Ignoring command '%s'\n", cmd); 122 } 123 } 124 } 125 126 // Generate multiboot-structure initialization code 127 fprintf(o, "static struct multiboot_modinfo mbi_mods[%d];\n", n_modules + 1); 128 fprintf(o, "static struct multiboot_mmap mbi_mmaps[%d];\n", n_mmaps); 129 fprintf(o, "static struct multiboot_info mbi;\n\n"); 130 fprintf(o, "struct multiboot_info *molly_get_mbi(void) {\n"); 131 132 // Flags: 133 fprintf(o, " mbi.flags |= MULTIBOOT_INFO_FLAG_HAS_CMDLINE;\n"); 134 fprintf(o, " mbi.flags |= MULTIBOOT_INFO_FLAG_HAS_MODS;\n"); 135 fprintf(o, " mbi.flags |= MULTIBOOT_INFO_FLAG_HAS_ELF_SYMS;\n"); 136 fprintf(o, " mbi.flags |= MULTIBOOT_INFO_FLAG_HAS_MMAP;\n"); 137 138 // Kernel command line: 139 fprintf(o, " mbi.cmdline = (uint32_t)(uint64_t) \"%s\";\n", kernel_cmd_line); 140 141 // Modules: 142 fprintf(o, " mbi.mods_count = %d;\n", n_modules + 1); 143 fprintf(o, " mbi.mods_addr = (uint32_t)(uint64_t) mbi_mods;\n"); 144 fprintf(o, " mbi_mods[0].mod_start = (uint32_t)(uint64_t) &%s_start;\n", 145 kernel_symbol_prefix); 146 fprintf(o, " mbi_mods[0].mod_end = (uint32_t)(uint64_t) &%s_end;\n", 147 kernel_symbol_prefix); 148 fprintf(o, " mbi_mods[0].string = (uint32_t)(uint64_t) \"%s\";\n", 149 kernel_cmd_line); 150 151 for (int i = 0; i < n_modules; i ++) { 152 fprintf(o, " mbi_mods[%d].mod_start = (uint32_t)(uint64_t) &%s_start;\n", 153 i+1, module_symbol_prefix[i]); 154 fprintf(o, " mbi_mods[%d].mod_end = (uint32_t)(uint64_t) &%s_end;\n", 155 i+1, module_symbol_prefix[i]); 156 fprintf(o, " mbi_mods[%d].string = (uint32_t)(uint64_t) \"%s\";\n", 157 i+1, module_cmd_line[i]); 158 } 159 160 // MMAPS: 161 fprintf(o, " mbi.mmap_length = sizeof(mbi_mmaps);\n"); 162 fprintf(o, " mbi.mmap_addr = (uint32_t)(uint64_t) mbi_mmaps;\n"); 163 for (int i = 0; i < n_mmaps; i ++) { 164 fprintf(o, " mbi_mmaps[%d].size = sizeof(struct multiboot_mmap);\n", i); 165 fprintf(o, " mbi_mmaps[%d].base_addr = mbi_mmap%d[0];\n", i, i); 166 fprintf(o, " mbi_mmaps[%d].length = mbi_mmap%d[1];\n", i, i); 167 fprintf(o, " mbi_mmaps[%d].type = (int)mbi_mmap%d[2];\n", i, i); 168 } 169 fprintf(o, " return &mbi;\n"); 170 fprintf(o, "}\n\n"); 171 172 fclose(f); 173 fclose(o); 174 175 return 0; 176} 177