diff options
author | Patrick Georgi <patrick.georgi@coresystems.de> | 2009-09-30 21:36:38 +0000 |
---|---|---|
committer | Patrick Georgi <patrick.georgi@coresystems.de> | 2009-09-30 21:36:38 +0000 |
commit | 26dd71c2d766f0630216aa5b8055b1f3b1e339ed (patch) | |
tree | 78d0614fce4c086e3c5e8341bf96f0554517dd01 /src/boot/selfboot.c | |
parent | aeab4fcca0ddea315ed3222eecd8ad74269c3924 (diff) | |
download | coreboot-26dd71c2d766f0630216aa5b8055b1f3b1e339ed.tar.xz |
Fix payload loading in various corner cases when working
with the bounce buffer.
In particular, the not-so-rare configuration of AMD boards with RAMBASE at
2MB shouldn't crash anymore for payloads that take > 1MB in total
Signed-off-by: Patrick Georgi <patrick.georgi@coresystems.de>
Acked-by: Ronald G. Minnich <rminnich@gmail.com>
git-svn-id: svn://svn.coreboot.org/coreboot/trunk@4697 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
Diffstat (limited to 'src/boot/selfboot.c')
-rw-r--r-- | src/boot/selfboot.c | 27 |
1 files changed, 22 insertions, 5 deletions
diff --git a/src/boot/selfboot.c b/src/boot/selfboot.c index 9f5fb5c440..bedb719808 100644 --- a/src/boot/selfboot.c +++ b/src/boot/selfboot.c @@ -423,14 +423,13 @@ static int load_self_segments( { struct segment *ptr; - unsigned long required_bounce_size = lb_end - lb_start; + unsigned long bounce_high = lb_end; for(ptr = head->next; ptr != head; ptr = ptr->next) { if (!overlaps_coreboot(ptr)) continue; - unsigned long bounce = ptr->s_dstaddr + ptr->s_memsz - lb_start; - if (bounce > required_bounce_size) - required_bounce_size = bounce; + if (ptr->s_dstaddr + ptr->s_memsz > bounce_high) + bounce_high = ptr->s_dstaddr + ptr->s_memsz; } - get_bounce_buffer(mem, required_bounce_size); + get_bounce_buffer(mem, bounce_high - lb_start); if (!bounce_buffer) { printk_err("Could not find a bounce buffer...\n"); return 0; @@ -502,6 +501,24 @@ static int load_self_segments( /* Zero the extra bytes */ memset(middle, 0, end - middle); } + /* Copy the data that's outside the area that shadows coreboot_ram */ + printk_debug("dest %lx, end %lx, bouncebuffer %lx\n", dest, end, bounce_buffer); + if ((unsigned long)end > bounce_buffer) { + if ((unsigned long)dest < bounce_buffer) { + unsigned long from = dest; + unsigned long to = lb_start-(bounce_buffer-(unsigned long)dest); + unsigned long amount = bounce_buffer-(unsigned long)dest; + printk_debug("move prefix around: from %lx, to %lx, amount: %lx\n", from, to, amount); + memcpy(to, from, amount); + } + if ((unsigned long)end > bounce_buffer + (lb_end - lb_start)) { + unsigned long from = bounce_buffer + (lb_end - lb_start); + unsigned long to = lb_end; + unsigned long amount = end - from; + printk_debug("move suffix around: from %lx, to %lx, amount: %lx\n", from, to, amount); + memcpy(to, from, amount); + } + } } } return 1; |