From 9d60b0be1b6dd69614c968b009997ef535c14409 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Sun, 26 Apr 2009 19:29:33 -0700 Subject: [PATCH] mboot: fix cmdline; a few more layout tweaks Fix module command lines (it was overwriting the main kernel command line); a few minor layout tweaks. In particular, we require the section header to be page-aligned, but not the subsequent sections. With this, I can get Xen to boot. Signed-off-by: H. Peter Anvin --- com32/mboot/map.c | 20 ++++++++++++-------- com32/mboot/mboot.c | 42 ++++++++++++++++++++++-------------------- com32/mboot/mboot.h | 4 +++- com32/mboot/mem.c | 2 +- 4 files changed, 38 insertions(+), 30 deletions(-) diff --git a/com32/mboot/map.c b/com32/mboot/map.c index d872d90..b134a55 100644 --- a/com32/mboot/map.c +++ b/com32/mboot/map.c @@ -37,7 +37,7 @@ static struct syslinux_movelist *ml = NULL; static struct syslinux_memmap *mmap = NULL, *amap = NULL; static struct multiboot_header *mbh; -static addr_t mboot_high_water_mark = 0; +static addr_t mboot_high_water_mark = 0x100000; /* * Note: although there is no such thing in the spec, at least Xen makes @@ -48,11 +48,11 @@ static addr_t mboot_high_water_mark = 0; * As a precaution, this also pads the data with zero up to the next * alignment datum. */ -addr_t map_data(const void *data, size_t len, int align, bool high) +addr_t map_data(const void *data, size_t len, size_t align, int flags) { - addr_t start = high ? mboot_high_water_mark : 0x800; - addr_t pad = -len & (align-1); - addr_t xlen = len+pad; + addr_t start = (flags & MAP_HIGH) ? mboot_high_water_mark : 0x2000; + addr_t pad = (flags & MAP_NOPAD) ? 0 : -len & (align-1); + addr_t xlen = len+pad; if (syslinux_memmap_find(amap, SMT_FREE, &start, &xlen, align) || syslinux_add_memmap(&amap, start, len+pad, SMT_ALLOC) || @@ -75,7 +75,7 @@ addr_t map_string(const char *string) if (!string) return 0; else - return map_data(string, strlen(string)+1, 4, true); + return map_data(string, strlen(string)+1, 1, 0); } int map_image(void *ptr, size_t len) @@ -217,7 +217,11 @@ int map_image(void *ptr, size_t len) sh = (Elf32_Shdr *)((char *)eh + eh->e_shoff); len = eh->e_shentsize * eh->e_shnum; - addr = map_data(sh, len, 4096, true); + /* + * Align this, but don't pad -- in general this means a bunch of + * smaller sections gets packed into a single page. + */ + addr = map_data(sh, len, 4096, MAP_HIGH|MAP_NOPAD); if (!addr) { error("Failed to map symbol table\n"); goto bail; @@ -239,7 +243,7 @@ int map_image(void *ptr, size_t len) align = sh[i].sh_addralign ? sh[i].sh_addralign : 0; addr = map_data((char *)ptr + sh[i].sh_offset, sh[i].sh_size, - align, true); + align, MAP_HIGH); if (!addr) { error("Failed to map symbol section\n"); goto bail; diff --git a/com32/mboot/mboot.c b/com32/mboot/mboot.c index fcde53d..3b42093 100644 --- a/com32/mboot/mboot.c +++ b/com32/mboot/mboot.c @@ -56,13 +56,21 @@ static int map_modules(struct module_data *modules, int nmodules) return -1; } + map_list = map_data(mod_list, list_size, 16, 0); + if (!map_list) { + printf("Cannot map module list\n"); + return -1; + } + for (i = 0; i < nmodules; i++) { addr_t mod_map = 0; addr_t cmd_map = 0; + dprintf("Module %d cmdline: \"%s\"\n", i, modules[i].cmdline); + cmd_map = map_string(modules[i].cmdline); - mod_map = map_data(modules[i].data, modules[i].len, 4096, true); + mod_map = map_data(modules[i].data, modules[i].len, 4096, MAP_HIGH); if (!mod_map) { printf("Failed to map module (memory fragmentation issue?)\n"); return -1; @@ -73,12 +81,6 @@ static int map_modules(struct module_data *modules, int nmodules) mod_list[i].pad = 0; } - map_list = map_data(mod_list, list_size, 16, false); - if (!map_list) { - printf("Cannot map module list\n"); - return -1; - } - mbinfo.flags |= MB_INFO_MODS; mbinfo.mods_count = nmodules; mbinfo.mods_addr = map_list; @@ -88,7 +90,7 @@ static int map_modules(struct module_data *modules, int nmodules) static int get_modules(char **argv, struct module_data **mdp) { char **argp, **argx; - struct module_data *md, *mp; + struct module_data *mp; int rv; int module_count = 1; int arglen; @@ -99,13 +101,12 @@ static int get_modules(char **argv, struct module_data **mdp) module_count++; } - *mdp = md = malloc(module_count * sizeof(struct module_data)); - if (!md) { + *mdp = mp = malloc(module_count * sizeof(struct module_data)); + if (!mp) { error("Out of memory!\n"); return -1; } - mp = md; argp = argv; while (*argp) { /* Note: it seems Grub transparently decompresses all compressed files, @@ -125,10 +126,10 @@ static int get_modules(char **argv, struct module_data **mdp) arglen += strlen(*argx)+1; if (arglen == 0) { - mp->cmdline = NULL; + mp->cmdline = strdup(""); } else { char *p; - md->cmdline = p = malloc(arglen); + mp->cmdline = p = malloc(arglen); for ( ; *argp && strcmp(*argp, module_separator); argp++) { p = strpcpy(p, *argp); *p++ = ' '; @@ -170,14 +171,8 @@ int main(int argc, char *argv[]) if (map_image(modules[0].data, modules[0].len)) return 1; - /* Map auxilliary images */ - if (nmodules > 1) { - if (map_modules(modules+1, nmodules-1)) - return 1; - } - /* Map the mbinfo structure */ - regs.ebx = map_data(&mbinfo, sizeof mbinfo, 4, false); + regs.ebx = map_data(&mbinfo, sizeof mbinfo, 4, 0); if (!regs.ebx) { error("Failed to map Multiboot info structure!\n"); return 1; @@ -186,10 +181,17 @@ int main(int argc, char *argv[]) /* Map the primary command line */ if (modules[0].cmdline) { mbinfo.cmdline = map_string(modules[0].cmdline); + dprintf("Main cmdline: \"%s\"\n", modules[0].cmdline); if (mbinfo.cmdline) mbinfo.flags |= MB_INFO_CMDLINE; } + /* Map auxilliary images */ + if (nmodules > 1) { + if (map_modules(modules+1, nmodules-1)) + return 1; + } + /* Add auxilliary information */ mboot_make_memmap(); mboot_apm(); diff --git a/com32/mboot/mboot.h b/com32/mboot/mboot.h index bf5d81c..0f33a51 100644 --- a/com32/mboot/mboot.h +++ b/com32/mboot/mboot.h @@ -71,7 +71,9 @@ extern struct multiboot_info mbinfo; extern struct syslinux_pm_regs regs; /* map.c */ -addr_t map_data(const void *data, size_t len, int align, bool high); +#define MAP_HIGH 1 +#define MAP_NOPAD 2 +addr_t map_data(const void *data, size_t len, size_t align, int flags); addr_t map_string(const char *string); int map_image(void *ptr, size_t len); void mboot_run(int bootflags); diff --git a/com32/mboot/mem.c b/com32/mboot/mem.c index ecbf5c1..e9d8bbd 100644 --- a/com32/mboot/mem.c +++ b/com32/mboot/mem.c @@ -206,7 +206,7 @@ void mboot_make_memmap(void) mbinfo.mem_upper = (highmem - 0x100000) >> 10; mbinfo.flags |= MB_INFO_MEMORY; - /* XXX: Should this be +4? */ + /* The spec says this address should be +4, but Grub disagrees */ mbinfo.mmap_addr = map_data(ard, nmap*sizeof *ard, 4, false); if (mbinfo.mmap_addr) { mbinfo.mmap_length = nmap*sizeof *ard; -- 2.7.4