1/* 2 * M5 boot image tool. 3 * 4 */ 5 6#include <stdio.h> 7#include <stdlib.h> 8#include <stdint.h> 9#include <stddef.h> 10#include <stdbool.h> 11#include <string.h> 12#include <assert.h> 13#include <ctype.h> 14#include <inttypes.h> 15#include "elf.h" 16 17 18//XXX: hardcoded start address of ramdisk 19// has to match the address specified in tools/arm_gem5/gem5script.py 20#define INITRD_BASE 0x10000000 21 22#define MAX_MODULES 256 23 24static char *kernel_symbol_prefix; 25static char *kernel_cmd_line; 26static char *module_symbol_prefix[MAX_MODULES]; 27static char *module_cmd_line[MAX_MODULES]; 28 29 30static char *get_symbol_name_prefix(char *original) { 31 char *prefix = "_binary__"; 32 char *r = malloc(strlen(prefix) + strlen(original) + 1); 33 sprintf(r, "%s%s", prefix, original); 34 for (int i = 0; i < strlen(r); i ++) { 35 if (r[i] == '/') { 36 r[i] = '_'; 37 } 38 if (r[i] == '-') {//needed for armv7-m 39 r[i] = '_'; 40 } 41 } 42 return r; 43} 44 45int main(int argc, char *argv[]) 46{ 47 int n_modules = 0; 48 int n_mmaps = 0; 49 bool aarch64 = false; 50 51 if(argc < 3 || (argc == 4 && strcmp("-64", argv[3]) 52 && strcmp("-32", argv[3]))) { 53 printf("Usage: %s <menu.lst> <output.c> [-64|-32]\n", argv[0]); 54 return 0; 55 } 56 57 if(argc >= 4 && !strcmp("-64", argv[3])) aarch64 = true; 58 59 FILE *f = fopen(argv[1], "r"); 60 assert((f != NULL) && "Could not open input file"); 61 62 FILE *o = fopen(argv[2], "w"); 63 assert((o != NULL) && "Could not open output file"); 64 65 // Output initial part of file: include basic types etc. 66 fprintf(o, "#include <assert.h>\n"); 67 fprintf(o, "#include <stdio.h>\n"); 68 fprintf(o, "#include <stdint.h>\n"); 69 fprintf(o, "#include <stddef.h>\n"); 70 fprintf(o, "#include <string.h>\n"); 71 fprintf(o, "#include <barrelfish_kpi/types.h>\n"); 72 fprintf(o, "#include <errors/errno.h>\n"); 73 fprintf(o, "#include <elf/elf.h>\n"); 74 fprintf(o, "#include <multiboot.h>\n"); 75 76 // Process menu.lst, generating definitions 77 char cmd[1024], args[1024], image[1024]; 78 while(!feof(f)) { 79 char line[1024], *l; 80 81 cmd[0] = args[0] = image[0] = line[0] = '\0'; 82 83 l = fgets(line, 1024, f); 84 if (!l) { 85 /* error or EOF, check for EOF with next iteration */ 86 continue; 87 } 88 sscanf(line, "%s %s %[^\n]", cmd, image, args); 89 90 if(!strcmp(cmd, "kernel")) { 91 kernel_symbol_prefix = get_symbol_name_prefix(image); 92 kernel_cmd_line = malloc(strlen(line) + 1); 93 sprintf(kernel_cmd_line, "%s %s", image, args); 94 fprintf(o, "extern char %s_start;\n", kernel_symbol_prefix); 95 fprintf(o, "extern char %s_end;\n", kernel_symbol_prefix); 96 } else if(!strcmp(cmd, "module") || !strcmp(cmd, "modulenounzip")) { 97 assert(n_modules < MAX_MODULES); 98 module_symbol_prefix[n_modules] = get_symbol_name_prefix(image); 99 module_cmd_line[n_modules] = malloc(strlen(line) + 1); 100 sprintf(module_cmd_line[n_modules], "%s %s", image, args); 101 fprintf(o, "extern char %s_start;\n", module_symbol_prefix[n_modules]); 102 fprintf(o, "extern char %s_end;\n", module_symbol_prefix[n_modules]); 103 n_modules ++; 104 } else if(!strcmp(cmd, "mmap")) { 105 if(aarch64) { 106 uint64_t base, len; 107 int type; 108 sscanf(args, "%" SCNi64 " %" SCNi64 " %i", 109 &base, &len, &type); 110 printf("Inserting MMAP %d: [0x%" PRIx64 ", 0x%" PRIx64 "], type %d\n", 111 n_mmaps, base, len, type); 112 fprintf(o, "static uint64_t mbi_mmap%d[] = {0x%" PRIx64 113 ", 0x%" PRIx64 ", %d};\n", 114 n_mmaps, base, len, type); 115 } 116 else { 117 uint32_t base, len; 118 int type; 119 sscanf(args, "%" SCNi32 " %" SCNi32 " %i", 120 &base, &len, &type); 121 printf("Inserting MMAP %d: [0x%" PRIx32 ", 0x%" PRIx32 "], type %d\n", 122 n_mmaps, base, len, type); 123 fprintf(o, "static uint32_t mbi_mmap%d[] = {0x%" PRIx32 124 ", 0x%" PRIx32 ", %d};\n", 125 n_mmaps, base, len, type); 126 } 127 n_mmaps ++; 128 } else { 129 bool iscmd = false; 130 for(int i = 0; i < strlen(cmd); i++) { 131 if(cmd[i] == '#') { 132 break; 133 } 134 if(!isspace(cmd[i])) { 135 iscmd = true; 136 break; 137 } 138 } 139 if(iscmd) { 140 printf("Ignoring command '%s'\n", cmd); 141 } 142 } 143 } 144 145 // Generate multiboot-structure initialization code 146 fprintf(o, "static struct multiboot_modinfo mbi_mods[%d];\n", n_modules + 1); 147 fprintf(o, "static struct multiboot_mmap mbi_mmaps[%d];\n", n_mmaps); 148 fprintf(o, "static struct multiboot_info mbi;\n\n"); 149 fprintf(o, "struct multiboot_info *molly_get_mbi(void) {\n"); 150 151 // Initialize all static data structures 152 fprintf(o, "memset(&mbi, 0, sizeof(struct multiboot_info));\n"); 153 fprintf(o, "memset(&mbi_mods, 0, sizeof(mbi_mods));\n"); 154 fprintf(o, "memset(&mbi_mmaps, 0, sizeof(mbi_mmaps));\n"); 155 156 // Flags: 157 fprintf(o, " mbi.flags |= MULTIBOOT_INFO_FLAG_HAS_CMDLINE;\n"); 158 fprintf(o, " mbi.flags |= MULTIBOOT_INFO_FLAG_HAS_MODS;\n"); 159 fprintf(o, " mbi.flags |= MULTIBOOT_INFO_FLAG_HAS_ELF_SYMS;\n"); 160 fprintf(o, " mbi.flags |= MULTIBOOT_INFO_FLAG_HAS_MMAP;\n"); 161 162 // Kernel command line: 163 if(aarch64) 164 fprintf(o, " mbi.cmdline = (uint64_t) \"%s\";\n", kernel_cmd_line); 165 else 166 fprintf(o, " mbi.cmdline = (uint32_t) \"%s\";\n", kernel_cmd_line); 167 168 // Modules: 169 fprintf(o, " mbi.mods_count = %d;\n", n_modules + 1); 170 if(aarch64) { 171 fprintf(o, " mbi.mods_addr = (uint64_t) mbi_mods;\n"); 172 fprintf(o, " mbi_mods[0].mod_start = (uint64_t) &%s_start;\n", 173 kernel_symbol_prefix); 174 fprintf(o, " mbi_mods[0].mod_end = (uint64_t) &%s_end;\n", 175 kernel_symbol_prefix); 176 fprintf(o, " mbi_mods[0].string = (uint64_t)\"%s\";\n", 177 kernel_cmd_line); 178 179 for (int i = 0; i < n_modules; i ++) { 180 fprintf(o, " mbi_mods[%d].mod_start = (uint64_t) &%s_start;\n", 181 i+1, module_symbol_prefix[i]); 182 fprintf(o, " mbi_mods[%d].mod_end = (uint64_t) &%s_end;\n", 183 i+1, module_symbol_prefix[i]); 184 fprintf(o, " mbi_mods[%d].string = (uint64_t) \"%s\";\n", 185 i+1, module_cmd_line[i]); 186 } 187 } else { 188 fprintf(o, " mbi.mods_addr = (uint32_t) mbi_mods;\n"); 189 fprintf(o, " mbi_mods[0].mod_start = (uint32_t) &%s_start;\n", 190 kernel_symbol_prefix); 191 fprintf(o, " mbi_mods[0].mod_end = (uint32_t) &%s_end;\n", 192 kernel_symbol_prefix); 193 fprintf(o, " mbi_mods[0].string = (uint32_t)\"%s\";\n", 194 kernel_cmd_line); 195 196 for (int i = 0; i < n_modules; i ++) { 197 fprintf(o, " mbi_mods[%d].mod_start = (uint32_t) &%s_start;\n", 198 i+1, module_symbol_prefix[i]); 199 fprintf(o, " mbi_mods[%d].mod_end = (uint32_t) &%s_end;\n", 200 i+1, module_symbol_prefix[i]); 201 fprintf(o, " mbi_mods[%d].string = (uint32_t) \"%s\";\n", 202 i+1, module_cmd_line[i]); 203 } 204 } 205 206 // MMAPS: 207 fprintf(o, " mbi.mmap_length = sizeof(mbi_mmaps);\n"); 208 if(aarch64) 209 fprintf(o, " mbi.mmap_addr = (uint64_t) mbi_mmaps;\n"); 210 else 211 fprintf(o, " mbi.mmap_addr = (uint32_t) mbi_mmaps;\n"); 212 for (int i = 0; i < n_mmaps; i ++) { 213 fprintf(o, " mbi_mmaps[%d].size = sizeof(struct multiboot_mmap);\n", i); 214 fprintf(o, " mbi_mmaps[%d].base_addr = mbi_mmap%d[0];\n", i, i); 215 fprintf(o, " mbi_mmaps[%d].length = mbi_mmap%d[1];\n", i, i); 216 fprintf(o, " mbi_mmaps[%d].type = (int)mbi_mmap%d[2];\n", i, i); 217 } 218 fprintf(o, " return &mbi;\n"); 219 fprintf(o, "}\n\n"); 220 221 fclose(f); 222 fclose(o); 223 224 return 0; 225} 226