summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@linux.intel.com>2010-06-08 10:58:48 -0700
committerH. Peter Anvin <hpa@linux.intel.com>2010-06-08 10:58:48 -0700
commitac968004da9f0003db92e9becca828c2685a24ad (patch)
tree60d9a4a120aca17bdc46945777b0faf0d92d2902
parentcd508a8c968deda3b91a6c46ba1a1572753f3951 (diff)
downloadsyslinux-ac968004da9f0003db92e9becca828c2685a24ad.tar.gz
mboot.c32: handle non-self-terminating images
Handle non-ELF Multiboot images with 0 entries for data and/or bss end, which means "until end of the file" and "nothing" for the two fields, respectively. Reported-and-tested-by: Thomas Bächler <thomas@archlinux.org> Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
-rw-r--r--com32/mboot/map.c20
1 files changed, 14 insertions, 6 deletions
diff --git a/com32/mboot/map.c b/com32/mboot/map.c
index 267e50c8..537741e6 100644
--- a/com32/mboot/map.c
+++ b/com32/mboot/map.c
@@ -107,15 +107,15 @@ struct multiboot_header *map_image(void *ptr, size_t len)
Elf32_Ehdr *eh = ptr;
Elf32_Phdr *ph;
Elf32_Shdr *sh;
- unsigned int i;
+ unsigned int i, mbh_offset;
uint32_t bad_flags;
/*
* Search for the multiboot header...
*/
mbh_len = 0;
- for (i = 0; i < MULTIBOOT_SEARCH; i += 4) {
- mbh = (struct multiboot_header *)((char *)ptr + i);
+ for (mbh_offset = 0; mbh_offset < MULTIBOOT_SEARCH; mbh_offset += 4) {
+ mbh = (struct multiboot_header *)((char *)ptr + mbh_offset);
if (mbh->magic != MULTIBOOT_MAGIC)
continue;
if (mbh->magic + mbh->flags + mbh->checksum)
@@ -127,7 +127,7 @@ struct multiboot_header *map_image(void *ptr, size_t len)
else
mbh_len = 12;
- if (i + mbh_len > len)
+ if (mbh_offset + mbh_len > len)
mbh_len = 0; /* Invalid... */
else
break; /* Found something... */
@@ -276,8 +276,16 @@ struct multiboot_header *map_image(void *ptr, size_t len)
regs.eip = mbh->entry_addr;
data_ptr = (char *)mbh - (mbh->header_addr - mbh->load_addr);
- data_len = mbh->load_end_addr - mbh->load_addr;
- bss_len = mbh->bss_end_addr - mbh->load_end_addr;
+
+ if (mbh->load_end_addr)
+ data_len = mbh->load_end_addr - mbh->load_addr;
+ else
+ data_len = len - mbh_offset + (mbh->header_addr - mbh->load_addr);
+
+ if (mbh->bss_end_addr)
+ bss_len = mbh->bss_end_addr - mbh->load_end_addr;
+ else
+ bss_len = 0;
if (syslinux_memmap_type(amap, mbh->load_addr, data_len + bss_len)
!= SMT_FREE) {