diff options
author | H. Peter Anvin <hpa@zytor.com> | 2009-03-10 14:36:36 -0700 |
---|---|---|
committer | H. Peter Anvin <hpa@zytor.com> | 2009-03-10 14:38:05 -0700 |
commit | 86981dec7307fd10f98410561107bde5bff7e10b (patch) | |
tree | 6f9c5f094f750a378647b1a8738c43d7ecdfaf61 /com32/lib/syslinux/shuffle.c | |
parent | 9c8898254752a8d29331ab838bb9794904a3f707 (diff) | |
download | syslinux-86981dec7307fd10f98410561107bde5bff7e10b.tar.gz |
shuffler: fix the handling of more than one block of descriptors
When allocating more than one block of descriptors, make sure we
account for all the memory used correctly. Otherwise, very bad things
happen.
Diffstat (limited to 'com32/lib/syslinux/shuffle.c')
-rw-r--r-- | com32/lib/syslinux/shuffle.c | 22 |
1 files changed, 15 insertions, 7 deletions
diff --git a/com32/lib/syslinux/shuffle.c b/com32/lib/syslinux/shuffle.c index cb2751af..edba4209 100644 --- a/com32/lib/syslinux/shuffle.c +++ b/com32/lib/syslinux/shuffle.c @@ -1,6 +1,6 @@ /* ----------------------------------------------------------------------- * * - * Copyright 2007-2008 H. Peter Anvin - All Rights Reserved + * Copyright 2007-2009 H. Peter Anvin - All Rights Reserved * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation @@ -76,7 +76,7 @@ int syslinux_prepare_shuffle(struct syslinux_movelist *fraglist, struct syslinux_movelist *moves = NULL, *mp; struct syslinux_memmap *rxmap = NULL, *ml; struct shuffle_descriptor *dp, *dbuf; - int np, nb, rv = -1; + int np, nb, nl, rv = -1; int desc_blocks, need_blocks; addr_t desczone, descfree, descaddr, descoffs; int nmoves, nzero; @@ -89,7 +89,7 @@ int syslinux_prepare_shuffle(struct syslinux_movelist *fraglist, nzero++; } - /* Find the larges contiguous region unused by input *and* output; + /* Find the largest contiguous region unused by input *and* output; this is where we put the move descriptor list */ rxmap = syslinux_dup_memmap(memmap); @@ -165,12 +165,13 @@ int syslinux_prepare_shuffle(struct syslinux_movelist *fraglist, /* Copy the move sequence into the descriptor buffer */ np = 0; nb = 0; + nl = nmoves+nzero; dp = dbuf; for (mp = moves; mp; mp = mp->next) { if (nb == DESC_BLOCK_SIZE-1) { dp->dst = -1; /* Load new descriptors */ dp->src = (addr_t)(dp+1) + descoffs; - dp->len = sizeof(*dp)*min(nmoves, DESC_BLOCK_SIZE); + dp->len = sizeof(*dp)*min(nl, DESC_BLOCK_SIZE); dprintf("[ %08x %08x %08x ]\n", dp->dst, dp->src, dp->len); dp++; np++; nb = 0; @@ -180,7 +181,7 @@ int syslinux_prepare_shuffle(struct syslinux_movelist *fraglist, dp->src = mp->src; dp->len = mp->len; dprintf("[ %08x %08x %08x ]\n", dp->dst, dp->src, dp->len); - dp++; np++; nb++; + dp++; np++; nb++; nl--; } /* Copy bzero operations into the descriptor buffer */ @@ -189,7 +190,7 @@ int syslinux_prepare_shuffle(struct syslinux_movelist *fraglist, if (nb == DESC_BLOCK_SIZE-1) { dp->dst = (addr_t)-1; /* Load new descriptors */ dp->src = (addr_t)(dp+1) + descoffs; - dp->len = sizeof(*dp)*min(nmoves, DESC_BLOCK_SIZE); + dp->len = sizeof(*dp)*min(nl, DESC_BLOCK_SIZE); dprintf("[ %08x %08x %08x ]\n", dp->dst, dp->src, dp->len); dp++; np++; nb = 0; @@ -199,10 +200,17 @@ int syslinux_prepare_shuffle(struct syslinux_movelist *fraglist, dp->src = (addr_t)-1; /* bzero region */ dp->len = ml->next->start - ml->start; dprintf("[ %08x %08x %08x ]\n", dp->dst, dp->src, dp->len); - dp++; np++; nb++; + dp++; np++; nb++; nl--; } } +#if DEBUG + if (np != nmoves+nzero+desc_blocks) { + dprintf("!!! np = %d : nmoves = %d, nzero = %d, desc_blocks = %d\n", + np, nmoves, nzero, desc_blocks); + } +#endif + /* Set up the primary descriptors in the bounce buffer. The first one moves the descriptor list into its designated safe zone, the second one loads the first descriptor block. */ |