lib/selfboot: clear BSS segments

For some reason the self loader wasn't clearing segments
marked as BSS type. Other segments which weren't fully
written by the file-backed content were being cleared up
to the indicated memsize. Treat segments marked BSS
similarly by clearing their content.

Change-Id: I9296c11a89455a02e5dd18bba13d4911517c04f6
Signed-off-by: Aaron Durbin <adurbin@chromium.org>
Reviewed-on: https://review.coreboot.org/15603
Tested-by: build bot (Jenkins)
Reviewed-by: Julius Werner <jwerner@chromium.org>
Reviewed-by: Furquan Shaikh <furquan@google.com>
Reviewed-by: Patrick Georgi <pgeorgi@google.com>
This commit is contained in:
Aaron Durbin 2016-07-11 15:36:50 -05:00
parent 0dd655f8a8
commit 044fb53a2e
1 changed files with 72 additions and 78 deletions

View File

@ -296,6 +296,7 @@ static int build_self_segment_list(
+ segment.offset;
new->s_dstaddr = segment.load_addr;
new->s_memsz = segment.mem_len;
new->compression = CBFS_COMPRESS_NONE;
break;
case PAYLOAD_SEGMENT_ENTRY:
@ -332,16 +333,9 @@ static int load_self_segments(
struct prog *payload)
{
struct segment *ptr;
struct segment *last_non_empty;
const unsigned long one_meg = (1UL << 20);
unsigned long bounce_high = lb_end;
/* Determine last non-empty loaded segment. */
last_non_empty = NULL;
for(ptr = head->next; ptr != head; ptr = ptr->next)
if (ptr->s_filesz != 0)
last_non_empty = ptr;
for(ptr = head->next; ptr != head; ptr = ptr->next) {
if (bootmem_region_targets_usable_ram(ptr->s_dstaddr,
ptr->s_memsz))
@ -384,7 +378,8 @@ static int load_self_segments(
}
for(ptr = head->next; ptr != head; ptr = ptr->next) {
unsigned char *dest, *src;
unsigned char *dest, *src, *middle, *end;
size_t len, memsz;
printk(BIOS_DEBUG, "Loading Segment: addr: 0x%016lx memsz: 0x%016lx filesz: 0x%016lx\n",
ptr->s_dstaddr, ptr->s_memsz, ptr->s_filesz);
@ -401,82 +396,81 @@ static int load_self_segments(
/* Compute the boundaries of the segment */
dest = (unsigned char *)(ptr->s_dstaddr);
src = (unsigned char *)(ptr->s_srcaddr);
len = ptr->s_filesz;
memsz = ptr->s_memsz;
end = dest + memsz;
/* Copy data from the initial buffer */
if (ptr->s_filesz) {
unsigned char *middle, *end;
size_t len = ptr->s_filesz;
size_t memsz = ptr->s_memsz;
switch(ptr->compression) {
case CBFS_COMPRESS_LZMA: {
printk(BIOS_DEBUG, "using LZMA\n");
timestamp_add_now(TS_START_ULZMA);
len = ulzman(src, len, dest, memsz);
timestamp_add_now(TS_END_ULZMA);
if (!len) /* Decompression Error. */
return 0;
break;
}
case CBFS_COMPRESS_LZ4: {
printk(BIOS_DEBUG, "using LZ4\n");
timestamp_add_now(TS_START_ULZ4F);
len = ulz4fn(src, len, dest, memsz);
timestamp_add_now(TS_END_ULZ4F);
if (!len) /* Decompression Error. */
return 0;
break;
}
case CBFS_COMPRESS_NONE: {
printk(BIOS_DEBUG, "it's not compressed!\n");
memcpy(dest, src, len);
break;
}
default:
printk(BIOS_INFO, "CBFS: Unknown compression type %d\n", ptr->compression);
return -1;
switch(ptr->compression) {
case CBFS_COMPRESS_LZMA: {
printk(BIOS_DEBUG, "using LZMA\n");
timestamp_add_now(TS_START_ULZMA);
len = ulzman(src, len, dest, memsz);
timestamp_add_now(TS_END_ULZMA);
if (!len) /* Decompression Error. */
return 0;
break;
}
end = dest + memsz;
middle = dest + len;
printk(BIOS_SPEW, "[ 0x%08lx, %08lx, 0x%08lx) <- %08lx\n",
(unsigned long)dest,
(unsigned long)middle,
(unsigned long)end,
(unsigned long)src);
/* Zero the extra bytes between middle & end */
if (middle < end) {
printk(BIOS_DEBUG, "Clearing Segment: addr: 0x%016lx memsz: 0x%016lx\n",
(unsigned long)middle, (unsigned long)(end - middle));
/* Zero the extra bytes */
memset(middle, 0, end - middle);
case CBFS_COMPRESS_LZ4: {
printk(BIOS_DEBUG, "using LZ4\n");
timestamp_add_now(TS_START_ULZ4F);
len = ulz4fn(src, len, dest, memsz);
timestamp_add_now(TS_END_ULZ4F);
if (!len) /* Decompression Error. */
return 0;
break;
}
/* Copy the data that's outside the area that shadows ramstage */
printk(BIOS_DEBUG, "dest %p, end %p, bouncebuffer %lx\n", dest, end, bounce_buffer);
if ((unsigned long)end > bounce_buffer) {
if ((unsigned long)dest < bounce_buffer) {
unsigned char *from = dest;
unsigned char *to = (unsigned char*)(lb_start-(bounce_buffer-(unsigned long)dest));
unsigned long amount = bounce_buffer-(unsigned long)dest;
printk(BIOS_DEBUG, "move prefix around: from %p, to %p, 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 = (unsigned long)end - from;
printk(BIOS_DEBUG, "move suffix around: from %lx, to %lx, amount: %lx\n", from, to, amount);
memcpy((char*)to, (char*)from, amount);
}
case CBFS_COMPRESS_NONE: {
printk(BIOS_DEBUG, "it's not compressed!\n");
memcpy(dest, src, len);
break;
}
/*
* Each architecture can perform additonal operations
* on the loaded segment
*/
prog_segment_loaded((uintptr_t)dest, ptr->s_memsz,
last_non_empty == ptr ? SEG_FINAL : 0);
default:
printk(BIOS_INFO, "CBFS: Unknown compression type %d\n", ptr->compression);
return -1;
}
/* Calculate middle after any changes to len. */
middle = dest + len;
printk(BIOS_SPEW, "[ 0x%08lx, %08lx, 0x%08lx) <- %08lx\n",
(unsigned long)dest,
(unsigned long)middle,
(unsigned long)end,
(unsigned long)src);
/* Zero the extra bytes between middle & end */
if (middle < end) {
printk(BIOS_DEBUG, "Clearing Segment: addr: 0x%016lx memsz: 0x%016lx\n",
(unsigned long)middle, (unsigned long)(end - middle));
/* Zero the extra bytes */
memset(middle, 0, end - middle);
}
/* Copy the data that's outside the area that shadows ramstage */
printk(BIOS_DEBUG, "dest %p, end %p, bouncebuffer %lx\n", dest, end, bounce_buffer);
if ((unsigned long)end > bounce_buffer) {
if ((unsigned long)dest < bounce_buffer) {
unsigned char *from = dest;
unsigned char *to = (unsigned char*)(lb_start-(bounce_buffer-(unsigned long)dest));
unsigned long amount = bounce_buffer-(unsigned long)dest;
printk(BIOS_DEBUG, "move prefix around: from %p, to %p, 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 = (unsigned long)end - from;
printk(BIOS_DEBUG, "move suffix around: from %lx, to %lx, amount: %lx\n", from, to, amount);
memcpy((char*)to, (char*)from, amount);
}
}
/*
* Each architecture can perform additonal operations
* on the loaded segment
*/
prog_segment_loaded((uintptr_t)dest, ptr->s_memsz,
ptr->next == head ? SEG_FINAL : 0);
}
return 1;