summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2009-04-26 19:29:33 -0700
committerH. Peter Anvin <hpa@zytor.com>2009-04-26 19:29:33 -0700
commit9d60b0be1b6dd69614c968b009997ef535c14409 (patch)
treed36a082b14613d1c7eca2bd4156ba687e8e08a8f
parent8575c10e6da46ce0c806066668eff786ed9a2f2a (diff)
downloadsyslinux-9d60b0be1b6dd69614c968b009997ef535c14409.tar.gz
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 <hpa@zytor.com>
-rw-r--r--com32/mboot/map.c20
-rw-r--r--com32/mboot/mboot.c42
-rw-r--r--com32/mboot/mboot.h4
-rw-r--r--com32/mboot/mem.c2
4 files changed, 38 insertions, 30 deletions
diff --git a/com32/mboot/map.c b/com32/mboot/map.c
index d872d904..b134a558 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 fcde53d3..3b42093f 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 bf5d81cd..0f33a511 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 ecbf5c1c..e9d8bbdb 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;