Author: oxygene Date: 2009-05-13 18:27:25 +0200 (Wed, 13 May 2009) New Revision: 4281
Modified: trunk/coreboot-v2/src/arch/i386/boot/boot.c trunk/coreboot-v2/src/arch/ppc/boot/boot.c trunk/coreboot-v2/src/boot/elfboot.c trunk/coreboot-v2/src/boot/selfboot.c trunk/coreboot-v2/src/include/boot/elf.h Log: Allow dynamic size for the {s,}elfboot bounce buffer. Use that to fix selfboot with compressed payloads.
Signed-off-by: Patrick Georgi patrick.georgi@coresystems.de Acked-by: Ronald G. Minnich rminnich@gmail.com
Modified: trunk/coreboot-v2/src/arch/i386/boot/boot.c =================================================================== --- trunk/coreboot-v2/src/arch/i386/boot/boot.c 2009-05-13 14:39:59 UTC (rev 4280) +++ trunk/coreboot-v2/src/arch/i386/boot/boot.c 2009-05-13 16:27:25 UTC (rev 4281) @@ -68,7 +68,7 @@ }
-void jmp_to_elf_entry(void *entry, unsigned long buffer) +void jmp_to_elf_entry(void *entry, unsigned long buffer, unsigned long bounce_size) { extern unsigned char _ram_seg, _eram_seg; unsigned long lb_start, lb_size; @@ -79,7 +79,7 @@
lb_start = (unsigned long)&_ram_seg; lb_size = (unsigned long)(&_eram_seg - &_ram_seg); - adjust = buffer + lb_size - lb_start; + adjust = buffer + bounce_size - lb_start;
adjusted_boot_notes = (unsigned long)&elf_boot_notes; adjusted_boot_notes += adjust;
Modified: trunk/coreboot-v2/src/arch/ppc/boot/boot.c =================================================================== --- trunk/coreboot-v2/src/arch/ppc/boot/boot.c 2009-05-13 14:39:59 UTC (rev 4280) +++ trunk/coreboot-v2/src/arch/ppc/boot/boot.c 2009-05-13 16:27:25 UTC (rev 4281) @@ -16,7 +16,7 @@ }
-void jmp_to_elf_entry(void *entry, unsigned long buffer) +void jmp_to_elf_entry(void *entry, unsigned long buffer, unsigned long bounce_size) { void (*kernel_entry)(void);
Modified: trunk/coreboot-v2/src/boot/elfboot.c =================================================================== --- trunk/coreboot-v2/src/boot/elfboot.c 2009-05-13 14:39:59 UTC (rev 4280) +++ trunk/coreboot-v2/src/boot/elfboot.c 2009-05-13 16:27:25 UTC (rev 4281) @@ -122,6 +122,8 @@ * */
+static unsigned long bounce_size; + static unsigned long get_bounce_buffer(struct lb_memory *mem) { unsigned long lb_size; @@ -130,7 +132,8 @@ int i; lb_size = (unsigned long)(&_eram_seg - &_ram_seg); /* Double coreboot size so I have somewhere to place a copy to return to */ - lb_size = lb_size + lb_size; + bounce_size = lb_size; + lb_size = bounce_size + lb_size; mem_entries = (mem->size - sizeof(*mem))/sizeof(mem->map[0]); buffer = 0; for(i = 0; i < mem_entries; i++) { @@ -610,7 +613,7 @@ post_code(0xfe);
/* Jump to kernel */ - jmp_to_elf_entry(entry, bounce_buffer); + jmp_to_elf_entry(entry, bounce_buffer, bounce_size); return 1;
out:
Modified: trunk/coreboot-v2/src/boot/selfboot.c =================================================================== --- trunk/coreboot-v2/src/boot/selfboot.c 2009-05-13 14:39:59 UTC (rev 4280) +++ trunk/coreboot-v2/src/boot/selfboot.c 2009-05-13 16:27:25 UTC (rev 4281) @@ -92,7 +92,9 @@ * */
-static unsigned long get_bounce_buffer(struct lb_memory *mem) +static unsigned long bounce_size, bounce_buffer; + +static void get_bounce_buffer(struct lb_memory *mem, unsigned long bounce_size) { unsigned long lb_size; unsigned long mem_entries; @@ -100,7 +102,7 @@ int i; lb_size = (unsigned long)(&_eram_seg - &_ram_seg); /* Double coreboot size so I have somewhere to place a copy to return to */ - lb_size = lb_size + lb_size; + lb_size = bounce_size + lb_size; mem_entries = (mem->size - sizeof(*mem))/sizeof(mem->map[0]); buffer = 0; for(i = 0; i < mem_entries; i++) { @@ -123,7 +125,7 @@ continue; buffer = tbuffer; } - return buffer; + bounce_buffer = buffer; }
static int valid_area(struct lb_memory *mem, unsigned long buffer, @@ -180,24 +182,34 @@ return 1; }
+static const unsigned long lb_start = (unsigned long)&_ram_seg; +static const unsigned long lb_end = (unsigned long)&_eram_seg; + +static int overlaps_coreboot(struct segment *seg) +{ + unsigned long start, end; + start = seg->s_dstaddr; + end = start + seg->s_memsz; + return !((end <= lb_start) || (start >= lb_end)); +} + static void relocate_segment(unsigned long buffer, struct segment *seg) { /* Modify all segments that want to load onto coreboot * to load onto the bounce buffer instead. */ - unsigned long lb_start = (unsigned long)&_ram_seg; - unsigned long lb_end = (unsigned long)&_eram_seg; unsigned long start, middle, end;
printk_spew("lb: [0x%016lx, 0x%016lx)\n", lb_start, lb_end);
+ /* I don't conflict with coreboot so get out of here */ + if (!overlaps_coreboot(seg)) + return; + start = seg->s_dstaddr; middle = start + seg->s_filesz; end = start + seg->s_memsz; - /* I don't conflict with coreboot so get out of here */ - if ((end <= lb_start) || (start >= lb_end)) - return;
printk_spew("segment: [0x%016lx, 0x%016lx, 0x%016lx)\n", start, middle, end); @@ -297,7 +309,7 @@
static int build_self_segment_list( struct segment *head, - unsigned long bounce_buffer, struct lb_memory *mem, + struct lb_memory *mem, struct cbfs_payload *payload, u32 *entry) { struct segment *new; @@ -369,32 +381,47 @@ new->phdr_prev = head->phdr_prev; head->phdr_prev->phdr_next = new; head->phdr_prev = new; - - /* Verify the memory addresses in the segment are valid */ - if (!valid_area(mem, bounce_buffer, new->s_dstaddr, new->s_memsz)) - goto out; - - /* Modify the segment to load onto the bounce_buffer if necessary. - */ - relocate_segment(bounce_buffer, new); } return 1; - out: - return 0; }
static int load_self_segments( - struct segment *head, struct cbfs_payload *payload) + struct segment *head, + struct lb_memory *mem, + struct cbfs_payload *payload) { unsigned long offset; struct segment *ptr; offset = 0; + unsigned long required_bounce_size = lb_end - lb_start; 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; + } + get_bounce_buffer(mem, required_bounce_size); + if (!bounce_buffer) { + printk_err("Could not find a bounce buffer...\n"); + return 0; + } + for(ptr = head->next; ptr != head; ptr = ptr->next) { + /* Verify the memory addresses in the segment are valid */ + if (!valid_area(mem, bounce_buffer, ptr->s_dstaddr, ptr->s_memsz)) + return 0; + } + for(ptr = head->next; ptr != head; ptr = ptr->next) { unsigned char *dest, *middle, *end, *src; printk_debug("Loading Segment: addr: 0x%016lx memsz: 0x%016lx filesz: 0x%016lx\n", ptr->s_dstaddr, ptr->s_memsz, ptr->s_filesz); + /* Modify the segment to load onto the bounce_buffer if necessary. + */ + relocate_segment(bounce_buffer, ptr); + + printk_debug("Post relocation: addr: 0x%016lx memsz: 0x%016lx filesz: 0x%016lx\n", + ptr->s_dstaddr, ptr->s_memsz, ptr->s_filesz); + /* Compute the boundaries of the segment */ dest = (unsigned char *)(ptr->s_dstaddr); src = (unsigned char *)(ptr->s_srcaddr); @@ -454,21 +481,13 @@ { u32 entry=0; struct segment head; - unsigned long bounce_buffer;
- /* Find a bounce buffer so I can load to coreboot's current location */ - bounce_buffer = get_bounce_buffer(mem); - if (!bounce_buffer) { - printk_err("Could not find a bounce buffer...\n"); - goto out; - } - /* Preprocess the self segments */ - if (!build_self_segment_list(&head, bounce_buffer, mem, payload, &entry)) + if (!build_self_segment_list(&head, mem, payload, &entry)) goto out;
/* Load the segments */ - if (!load_self_segments(&head, payload)) + if (!load_self_segments(&head, mem, payload)) goto out;
printk_spew("Loaded segments\n"); @@ -480,7 +499,7 @@ post_code(0xfe);
/* Jump to kernel */ - jmp_to_elf_entry((void*)entry, bounce_buffer); + jmp_to_elf_entry((void*)entry, bounce_buffer, bounce_size); return 1;
out:
Modified: trunk/coreboot-v2/src/include/boot/elf.h =================================================================== --- trunk/coreboot-v2/src/include/boot/elf.h 2009-05-13 14:39:59 UTC (rev 4280) +++ trunk/coreboot-v2/src/include/boot/elf.h 2009-05-13 16:27:25 UTC (rev 4281) @@ -390,7 +390,7 @@ #endif
int elf_check_arch(Elf_ehdr *ehdr); -void jmp_to_elf_entry(void *entry, unsigned long buffer); +void jmp_to_elf_entry(void *entry, unsigned long buffer, unsigned long bounce_size); struct lb_memory; int elfboot(struct lb_memory *mem); /* Temporary compile fix, FILO should be dropped from coreboot */