If the coreboot and filo overlap, it will "slice off" a piece at the
"beginning" or "end". In the beginning case, a new segment is inserted before the current one. But the ptr will move forward and doesn't seem to have any other chance to process the "new" segment. ptr ---------+ move ---> | V +--------+ +--------+ | | | | | new | <---> |current | <---> ..... | | | | +--------+ +--------+ Now we change the ptr to the previous one and restart the loop. The new and current segment will both be processed. Even if the current segment is done twice, no new segment will come up and ptr will move forward as we expect. +----------------ptr move ---> | V +--------+ +--------+ +--------+ | | | | | | | prev | <---> | new | <---> |current | <---> ..... | | | | | | +--------+ +--------+ +--------+ It is tested and fixes the crashing on my AMD Family 10 board. Some trailing whitespaces were deleted. Signed-off-by: Zheng Bao <zheng.bao@amd.com> Acked-by: Stefan Reinauer <stepan@coresystems.de> git-svn-id: svn://svn.coreboot.org/coreboot/trunk@4912 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
This commit is contained in:
parent
448509bb4e
commit
e6ad7fa4a6
|
@ -211,19 +211,21 @@ static int overlaps_coreboot(struct segment *seg)
|
||||||
return !((end <= lb_start) || (start >= lb_end));
|
return !((end <= lb_start) || (start >= lb_end));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void relocate_segment(unsigned long buffer, struct segment *seg)
|
static int relocate_segment(unsigned long buffer, struct segment *seg)
|
||||||
{
|
{
|
||||||
/* Modify all segments that want to load onto coreboot
|
/* Modify all segments that want to load onto coreboot
|
||||||
* to load onto the bounce buffer instead.
|
* to load onto the bounce buffer instead.
|
||||||
*/
|
*/
|
||||||
unsigned long start, middle, end;
|
/* ret: 1 : A new segment is inserted before the seg.
|
||||||
|
* 0 : A new segment is inserted after the seg, or no new one. */
|
||||||
|
unsigned long start, middle, end, ret = 0;
|
||||||
|
|
||||||
printk_spew("lb: [0x%016lx, 0x%016lx)\n",
|
printk_spew("lb: [0x%016lx, 0x%016lx)\n",
|
||||||
lb_start, lb_end);
|
lb_start, lb_end);
|
||||||
|
|
||||||
/* I don't conflict with coreboot so get out of here */
|
/* I don't conflict with coreboot so get out of here */
|
||||||
if (!overlaps_coreboot(seg))
|
if (!overlaps_coreboot(seg))
|
||||||
return;
|
return 0;
|
||||||
|
|
||||||
start = seg->s_dstaddr;
|
start = seg->s_dstaddr;
|
||||||
middle = start + seg->s_filesz;
|
middle = start + seg->s_filesz;
|
||||||
|
@ -270,6 +272,8 @@ static void relocate_segment(unsigned long buffer, struct segment *seg)
|
||||||
new->s_dstaddr,
|
new->s_dstaddr,
|
||||||
new->s_dstaddr + new->s_filesz,
|
new->s_dstaddr + new->s_filesz,
|
||||||
new->s_dstaddr + new->s_memsz);
|
new->s_dstaddr + new->s_memsz);
|
||||||
|
|
||||||
|
ret = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Slice off a piece at the end
|
/* Slice off a piece at the end
|
||||||
|
@ -319,6 +323,8 @@ static void relocate_segment(unsigned long buffer, struct segment *seg)
|
||||||
seg->s_dstaddr,
|
seg->s_dstaddr,
|
||||||
seg->s_dstaddr + seg->s_filesz,
|
seg->s_dstaddr + seg->s_filesz,
|
||||||
seg->s_dstaddr + seg->s_memsz);
|
seg->s_dstaddr + seg->s_memsz);
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -446,7 +452,10 @@ static int load_self_segments(
|
||||||
|
|
||||||
/* Modify the segment to load onto the bounce_buffer if necessary.
|
/* Modify the segment to load onto the bounce_buffer if necessary.
|
||||||
*/
|
*/
|
||||||
relocate_segment(bounce_buffer, ptr);
|
if (relocate_segment(bounce_buffer, ptr)) {
|
||||||
|
ptr = (ptr->prev)->prev;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
printk_debug("Post relocation: addr: 0x%016lx memsz: 0x%016lx filesz: 0x%016lx\n",
|
printk_debug("Post relocation: addr: 0x%016lx memsz: 0x%016lx filesz: 0x%016lx\n",
|
||||||
ptr->s_dstaddr, ptr->s_memsz, ptr->s_filesz);
|
ptr->s_dstaddr, ptr->s_memsz, ptr->s_filesz);
|
||||||
|
|
Loading…
Reference in New Issue