aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKevin O'Connor <kevin@koconnor.net>2010-07-27 01:14:11 -0400
committerKevin O'Connor <kevin@koconnor.net>2010-07-27 01:14:11 -0400
commitb4525a0ec176426788f293cce92160e6573e86b6 (patch)
treec0f5506290d97ba62d7ec72b20392fb6ba0c847b
parent0e27e19e2ff2f61b8374a246398e4cf0ae7fc9bd (diff)
downloadseabios-b4525a0ec176426788f293cce92160e6573e86b6.tar.gz
Handle unaligned sizes in iomemcpy().
This fixes a bug causing truncation of uncompressed files in cbfs_copyfile().
-rw-r--r--src/coreboot.c5
-rw-r--r--src/util.c11
2 files changed, 9 insertions, 7 deletions
diff --git a/src/coreboot.c b/src/coreboot.c
index 5d9a101a..db0063be 100644
--- a/src/coreboot.c
+++ b/src/coreboot.c
@@ -510,11 +510,10 @@ cbfs_copyfile(struct cbfs_file *file, void *dst, u32 maxlen)
void *src = (void*)file + ntohl(file->offset);
if (cbfs_iscomp(file)) {
// Compressed - copy to temp ram and uncompress it.
- u32 asize = ALIGN(size, 4);
- void *temp = malloc_tmphigh(asize);
+ void *temp = malloc_tmphigh(size);
if (!temp)
return -1;
- iomemcpy(temp, src, asize);
+ iomemcpy(temp, src, size);
int ret = ulzma(dst, maxlen, temp, size);
yield();
free(temp);
diff --git a/src/util.c b/src/util.c
index 2c22dfc3..8e02d1e0 100644
--- a/src/util.c
+++ b/src/util.c
@@ -202,24 +202,27 @@ memcpy(void *d1, const void *s1, size_t len)
return d1;
}
-// Copy from memory mapped IO. IO mem is very slow, so yield
-// periodically. 'len' must be 4 byte aligned.
+// Copy to/from memory mapped IO. IO mem is very slow, so yield
+// periodically.
void
iomemcpy(void *d, const void *s, u32 len)
{
yield();
- while (len) {
+ while (len > 3) {
u32 copylen = len;
if (copylen > 2048)
copylen = 2048;
- len -= copylen;
copylen /= 4;
+ len -= copylen * 4;
asm volatile(
"rep movsl (%%esi),%%es:(%%edi)"
: "+c"(copylen), "+S"(s), "+D"(d)
: : "cc", "memory");
yield();
}
+ if (len)
+ // Copy any remaining bytes.
+ memcpy(d, s, len);
}
void *