GSList* parse_module_list (Package *pkg, const char *str, const char *path) { GSList *split; GSList *iter; GSList *retval = NULL; split = split_module_list (str, path); iter = split; while (iter != NULL) { RequiredVersion *ver; char *p; char *start; p = iter->data; ver = g_new0 (RequiredVersion, 1); ver->comparison = ALWAYS_MATCH; ver->owner = pkg; retval = g_slist_prepend (retval, ver); while (*p && MODULE_SEPARATOR (*p)) ++p; start = p; while (*p && !isspace ((guchar)*p)) ++p; while (*p && MODULE_SEPARATOR (*p)) { *p = '\0'; ++p; } if (*start == '\0') { verbose_error ("Empty package name in Requires or Conflicts in file '%s'\n", path); exit (1); } ver->name = g_strdup (start); start = p; while (*p && !isspace ((guchar)*p)) ++p; while (*p && isspace ((guchar)*p)) { *p = '\0'; ++p; } if (*start != '\0') { if (strcmp (start, "=") == 0) ver->comparison = EQUAL; else if (strcmp (start, ">=") == 0) ver->comparison = GREATER_THAN_EQUAL; else if (strcmp (start, "<=") == 0) ver->comparison = LESS_THAN_EQUAL; else if (strcmp (start, ">") == 0) ver->comparison = GREATER_THAN; else if (strcmp (start, "<") == 0) ver->comparison = LESS_THAN; else if (strcmp (start, "!=") == 0) ver->comparison = NOT_EQUAL; else { verbose_error ("Unknown version comparison operator '%s' after package name '%s' in file '%s'\n", start, ver->name, path); exit (1); } } start = p; while (*p && !MODULE_SEPARATOR (*p)) ++p; while (*p && MODULE_SEPARATOR (*p)) { *p = '\0'; ++p; } if (ver->comparison != ALWAYS_MATCH && *start == '\0') { verbose_error ("Comparison operator but no version after package name '%s' in file '%s'\n", ver->name, path); exit (1); } if (*start != '\0') { ver->version = g_strdup (start); } g_assert (ver->name); iter = g_slist_next (iter); } g_slist_foreach (split, (GFunc) g_free, NULL); g_slist_free (split); retval = g_slist_reverse (retval); return retval; }
void exec_mb(char *kernel, char* modules) /* Get a Minix image into core, patch it up and execute. */ { int i; static char hdr[SECTOR_SIZE]; char *buf; u32_t vsec, addr, limit, n, totalmem = 0; u16_t kmagic, mode; char *console; char params[SECTOR_SIZE]; extern char *sbrk(int); char *verb; u32_t text_vaddr, text_paddr, text_filebytes, text_membytes; u32_t data_vaddr, data_paddr, data_filebytes, data_membytes; u32_t pc; u32_t text_offset, data_offset; i32_t segsize; int r; u32_t cs, ds; char *modstring, *mod; multiboot_info_t *mbinfo; multiboot_module_t *mbmodinfo; u32_t mbinfo_size, mbmodinfo_size; char *memvar; memory *mp; u32_t mod_cmdline_start, kernel_cmdline_start; u32_t modstringlen; int modnr; /* The stack is pretty deep here, so check if heap and stack collide. */ (void) sbrk(0); if ((verb= b_value(VERBOSEBOOTVARNAME)) != nil) verboseboot = a2l(verb); printf("\nLoading %s\n", kernel); vsec= 0; /* Load this sector from kernel next. */ addr= mem[0].base; /* Into this memory block. */ limit= mem[0].base + mem[0].size; if (limit > caddr) limit= caddr; /* set click size for get_segment */ click_size = PAGE_SIZE; k_flags = K_KHIGH|K_BRET|K_MEML|K_INT86|K_RET|K_HDR |K_HIGH|K_CHMEM|K_I386; /* big kernels must be loaded into extended memory */ addr= mem[1].base; limit= mem[1].base + mem[1].size; /* Get first sector */ DEBUGEXTRA(("get_sector\n")); if ((buf= get_sector(vsec++)) == nil) { DEBUGEXTRA(("get_sector failed\n")); return; } memcpy(hdr, buf, SECTOR_SIZE); /* Get ELF header */ DEBUGEXTRA(("read_header_elf\n")); r = read_header_elf(hdr, &text_vaddr, &text_paddr, &text_filebytes, &text_membytes, &data_vaddr, &data_paddr, &data_filebytes, &data_membytes, &pc, &text_offset, &data_offset); if (r < 0) { errno= ENOEXEC; return; } /* Read the text segment. */ addr = text_paddr; segsize = (i32_t) text_filebytes; vsec = text_offset / SECTOR_SIZE; DEBUGEXTRA(("get_segment(0x%lx, 0x%lx, 0x%lx, 0x%lx)\n", vsec, segsize, addr, limit)); if (!get_segment(&vsec, &segsize, &addr, limit)) return; DEBUGEXTRA(("get_segment done vsec=0x%lx size=0x%lx " "addr=0x%lx\n", vsec, segsize, addr)); /* Read the data segment. */ addr = data_paddr; segsize = (i32_t) data_filebytes; vsec = data_offset / SECTOR_SIZE; DEBUGEXTRA(("get_segment(0x%lx, 0x%lx, 0x%lx, 0x%lx)\n", vsec, segsize, addr, limit)); if (!get_segment(&vsec, &segsize, &addr, limit)) return; DEBUGEXTRA(("get_segment done vsec=0x%lx size=0x%lx " "addr=0x%lx\n", vsec, segsize, addr)); n = data_membytes - align(data_filebytes, click_size); /* Zero out bss. */ DEBUGEXTRA(("\nraw_clear(0x%lx, 0x%lx); limit=0x%lx... ", addr, n, limit)); if (addr + n > limit) { errno= ENOMEM; return; } raw_clear(addr, n); DEBUGEXTRA(("done\n")); addr+= n; /* Check the kernel magic number. */ raw_copy(mon2abs(&kmagic), data_paddr + MAGIC_OFF, sizeof(kmagic)); if (kmagic != KERNEL_D_MAGIC) { printf("Kernel magic number is incorrect (0x%x@0x%lx)\n", kmagic, data_paddr + MAGIC_OFF); errno= 0; return; } /* Translate the boot parameters to what Minix likes best. */ DEBUGEXTRA(("params2params(0x%x, 0x%x)... ", params, sizeof(params))); if (!params2params(params, sizeof(params))) { errno= 0; return; } DEBUGEXTRA(("done\n")); /* Create multiboot info struct */ mbinfo = malloc(sizeof(multiboot_info_t)); if (mbinfo == nil) { errno= ENOMEM; return; } memset(mbinfo, 0, sizeof(multiboot_info_t)); /* Module info structs start where kernel ends */ mbinfo->mods_addr = addr; modstring = strdup(modules); if (modstring == nil) {errno = ENOMEM; return; } modstringlen = strlen(modules); mbinfo->mods_count = split_module_list(modules); mbmodinfo_size = sizeof(multiboot_module_t) * mbinfo->mods_count; mbmodinfo = malloc(mbmodinfo_size); if (mbmodinfo == nil) { errno= ENOMEM; return; } addr+= mbmodinfo_size; addr= align(addr, click_size); mod_cmdline_start = mbinfo->mods_addr + sizeof(multiboot_module_t) * mbinfo->mods_count; raw_copy(mod_cmdline_start, mon2abs(modules), modstringlen+1); mbmodinfo[0].cmdline = mod_cmdline_start; modnr = 1; for (i= 0; i < modstringlen; ++i) { if (modules[i] == '\0') { mbmodinfo[modnr].cmdline = mod_cmdline_start + i + 1; ++modnr; } } kernel_cmdline_start = mod_cmdline_start + modstringlen + 1; mbinfo->cmdline = kernel_cmdline_start; raw_copy(kernel_cmdline_start, mon2abs(kernel), strlen(kernel)+1); mbinfo->flags = MULTIBOOT_INFO_MODS|MULTIBOOT_INFO_CMDLINE| MULTIBOOT_INFO_BOOTDEV|MULTIBOOT_INFO_MEMORY; mbinfo->boot_device = mbdev; mbinfo->mem_lower = mem[0].size/1024; mbinfo->mem_upper = mem[1].size/1024; for (i = 0, mod = strtok(modstring, " "); mod != nil; mod = strtok(nil, " "), i++) { mod = select_image(mod); if (mod == nil) {errno = 0; return; } mbmodinfo[i].mod_start = addr; mbmodinfo[i].mod_end = addr + image_bytes; mbmodinfo[i].pad = 0; segsize= image_bytes; vsec= 0; DEBUGEXTRA(("get_segment(0x%lx, 0x%lx, 0x%lx, 0x%lx)\n", vsec, segsize, addr, limit)); if (!get_segment(&vsec, &segsize, &addr, limit)) return; DEBUGEXTRA(("get_segment done vsec=0x%lx size=0x%lx " "addr=0x%lx\n", vsec, segsize, addr)); addr+= segsize; addr= align(addr, click_size); } free(modstring); DEBUGEXTRA(("modinfo raw_copy: dst 0x%lx src 0x%lx sz 0x%lx\n", mbinfo->mods_addr, mon2abs(mbmodinfo), mbmodinfo_size)); raw_copy(mbinfo->mods_addr, mon2abs(mbmodinfo), mbmodinfo_size); free(mbmodinfo); raw_copy(MULTIBOOT_INFO_ADDR, mon2abs(mbinfo), sizeof(multiboot_info_t)); free(mbinfo); /* Run the trailer function just before starting Minix. */ DEBUGEXTRA(("run_trailer()... ")); if (!run_trailer()) { errno= 0; return; } DEBUGEXTRA(("done\n")); /* Set the video to the required mode. */ if ((console= b_value("console")) == nil || (mode= a2x(console)) == 0) { mode= strcmp(b_value("chrome"), "color") == 0 ? COLOR_MODE : MONO_MODE; } DEBUGEXTRA(("set_mode(%d)... ", mode)); set_mode(mode); DEBUGEXTRA(("done\n")); /* Close the disk. */ DEBUGEXTRA(("dev_close()... ")); (void) dev_close(); DEBUGEXTRA(("done\n")); /* Minix. */ cs = ds = text_paddr; DEBUGEXTRA(("minix(0x%lx, 0x%lx, 0x%lx, 0x%x, 0x%x, 0x%lx)\n", pc, cs, ds, params, sizeof(params), 0)); minix(pc, cs, ds, params, sizeof(params), 0); if (!(k_flags & K_BRET)) { extern u32_t reboot_code; raw_copy(mon2abs(params), reboot_code, sizeof(params)); } parse_code(params); /* Return from Minix. Things may have changed, so assume nothing. */ fsok= -1; errno= 0; /* Read leftover character, if any. */ scan_keyboard(); /* Restore screen contents. */ restore_screen(); }