Skip to content

Commit

Permalink
Fix a bug in the ubldr introduced in the rev.283035. The new code
Browse files Browse the repository at this point in the history
fails to properly consider memory regions when the loader is
located below of those regions or engulfs their lower limit. This
results in "not enough RAM to load kernel" panic, which is totally
bogus. On top of that, there are some variables that can be left
unitialized in those cases, which might cause it fail with memory
access violation instead of panic while trying to load kernel to
a wrong or non-existing address of memory.
  • Loading branch information
sobomax committed Jun 13, 2015
1 parent 63d3fe1 commit 4850979
Showing 1 changed file with 13 additions and 0 deletions.
13 changes: 13 additions & 0 deletions sys/boot/uboot/lib/copy.c
Original file line number Diff line number Diff line change
Expand Up @@ -102,14 +102,18 @@ uboot_loadaddr(u_int type, void *data, uint64_t addr)
biggest_size = 0;
subldr = rounddown2((uintptr_t)_start, KERN_ALIGN);
eubldr = roundup2(uboot_heap_end, KERN_ALIGN);
printf("subldr=%lu, eubldr=%lu\n", (unsigned long)subldr, (unsigned long)eubldr);
for (i = 0; i < si->mr_no; i++) {
printf("si->mr[%d]: .flags=%d, .start=%lu, .size=%lu\n",
i, si->mr[i].flags, si->mr[i].start, si->mr[i].size);
if (si->mr[i].flags != MR_ATTR_DRAM)
continue;
sblock = roundup2(si->mr[i].start, KERN_ALIGN);
eblock = rounddown2(si->mr[i].start + si->mr[i].size,
KERN_ALIGN);
if (biggest_size == 0)
sblock += KERN_MINADDR;
printf(" sblock=%d, eblock=%d\n", sblock, eblock);
if (subldr >= sblock && subldr < eblock) {
if (subldr - sblock > eblock - eubldr) {
this_block = sblock;
Expand All @@ -118,7 +122,16 @@ uboot_loadaddr(u_int type, void *data, uint64_t addr)
this_block = eubldr;
this_size = eblock - eubldr;
}
} else if (subldr < sblock && eubldr < eblock) {
/* Loader is below or engulfs the sblock */
this_block = (eubldr < sblock) ? sblock : eubldr;
this_size = eblock - this_block;
} else {
this_block = 0;
this_size = 0;
}
printf(" this_block=%lu, this_size=%lu\n",
(unsigned long)this_block, (unsigned long)this_size);
if (biggest_size < this_size) {
biggest_block = this_block;
biggest_size = this_size;
Expand Down

0 comments on commit 4850979

Please sign in to comment.