* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA
*/
+#include <arch/byteorder.h>
#include <console/console.h>
#include <fallback.h>
#include <boot/elf.h>
#include <boot/elf_boot.h>
#include <boot/coreboot_tables.h>
-#include <ip_checksum.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <cbfs.h>
#include <lib.h>
-#ifndef CONFIG_BIG_ENDIAN
-#define ntohl(x) ( ((x&0xff)<<24) | ((x&0xff00)<<8) | \
- ((x&0xff0000) >> 8) | ((x&0xff000000) >> 24) )
-#else
-#define ntohl(x) (x)
-#endif
-
-/* Maximum physical address we can use for the coreboot bounce buffer.
- */
+/* Maximum physical address we can use for the coreboot bounce buffer. */
#ifndef MAX_ADDR
#define MAX_ADDR -1UL
#endif
+/* from coreboot_ram.ld: */
extern unsigned char _ram_seg;
extern unsigned char _eram_seg;
+static const unsigned long lb_start = (unsigned long)&_ram_seg;
+static const unsigned long lb_end = (unsigned long)&_eram_seg;
+
struct segment {
struct segment *next;
struct segment *prev;
- struct segment *phdr_next;
- struct segment *phdr_prev;
unsigned long s_dstaddr;
unsigned long s_srcaddr;
unsigned long s_memsz;
int compression;
};
-struct verify_callback {
- struct verify_callback *next;
- int (*callback)(struct verify_callback *vcb,
- Elf_ehdr *ehdr, Elf_phdr *phdr, struct segment *head);
- unsigned long desc_offset;
- unsigned long desc_addr;
-};
-
-struct ip_checksum_vcb {
- struct verify_callback data;
- unsigned short ip_checksum;
-};
-
-static int selfboot(struct lb_memory *mem, struct cbfs_payload *payload);
-
-void * cbfs_load_payload(struct lb_memory *lb_mem, const char *name)
-{
- struct cbfs_payload *payload;
-
- payload = (struct cbfs_payload *)cbfs_find_file(name, CBFS_TYPE_PAYLOAD);
- if (payload == NULL)
- return (void *) -1;
- printk(BIOS_DEBUG, "Got a payload\n");
-
- selfboot(lb_mem, payload);
- printk(BIOS_EMERG, "SELFBOOT RETURNED!\n");
-
- return (void *) -1;
-}
-
/* The problem:
* Static executables all want to share the same addresses
* in memory because only a few addresses are reliably present on
* - Coreboot is preserved, so it can be returned to.
* - The implementation is still relatively simple,
* and much simpler than the general case implemented in kexec.
- *
*/
static unsigned long bounce_size, bounce_buffer;
unsigned long mem_entries;
unsigned long buffer;
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_end - lb_start;
+ /* Plus coreboot size so I have somewhere
+ * to place a copy to return to.
+ */
lb_size = req_size + lb_size;
- mem_entries = (mem->size - sizeof(*mem))/sizeof(mem->map[0]);
+ mem_entries = (mem->size - sizeof(*mem)) / sizeof(mem->map[0]);
buffer = 0;
for(i = 0; i < mem_entries; i++) {
unsigned long mstart, mend;
*/
int i;
unsigned long end = start + len;
- unsigned long mem_entries = (mem->size - sizeof(*mem))/sizeof(mem->map[0]);
+ unsigned long mem_entries = (mem->size - sizeof(*mem)) /
+ sizeof(mem->map[0]);
/* See if I conflict with the bounce buffer */
if (end >= buffer) {
mtype = mem->map[i].type;
mstart = unpack_lb64(mem->map[i].start);
mend = mstart + unpack_lb64(mem->map[i].size);
- if ((mtype == LB_MEM_RAM) && (start < mend) && (end > mstart)) {
+ if ((mtype == LB_MEM_RAM) && (start >= mstart) && (end < mend)) {
break;
}
- if ((mtype == LB_MEM_TABLE) && (start < mend) && (end > mstart)) {
- printk(BIOS_ERR, "Payload is overwriting Coreboot tables.\n");
+ if ((mtype == LB_MEM_TABLE) && (start >= mstart) && (end < mend)) {
+ printk(BIOS_ERR, "Payload is overwriting coreboot tables.\n");
break;
}
}
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)
{
* to load onto the bounce buffer instead.
*/
/* ret: 1 : A new segment is inserted before the seg.
- * 0 : A new segment is inserted after the seg, or no new one. */
+ * 0 : A new segment is inserted after the seg, or no new one.
+ */
unsigned long start, middle, end, ret = 0;
printk(BIOS_SPEW, "lb: [0x%016lx, 0x%016lx)\n",
new->prev = seg->prev;
seg->prev->next = new;
seg->prev = new;
- /* Order by original program header order */
- new->phdr_next = seg;
- new->phdr_prev = seg->phdr_prev;
- seg->phdr_prev->phdr_next = new;
- seg->phdr_prev = new;
/* compute the new value of start */
start = seg->s_dstaddr;
new->prev = seg;
seg->next->prev = new;
seg->next = new;
- /* Order by original program header order */
- new->phdr_next = seg->phdr_next;
- new->phdr_prev = seg;
- seg->phdr_next->phdr_prev = new;
- seg->phdr_next = new;
printk(BIOS_SPEW, " late: [0x%016lx, 0x%016lx, 0x%016lx)\n",
new->s_dstaddr,
struct segment *ptr;
struct cbfs_payload_segment *segment, *first_segment;
memset(head, 0, sizeof(*head));
- head->phdr_next = head->phdr_prev = head;
head->next = head->prev = head;
first_segment = segment = &payload->segments;
segment->type == PAYLOAD_SEGMENT_CODE ? "code" : "data",
ntohl(segment->compression));
new = malloc(sizeof(*new));
- new->s_dstaddr = ntohl((u32) segment->load_addr);
+ new->s_dstaddr = ntohll(segment->load_addr);
new->s_memsz = ntohl(segment->mem_len);
new->compression = ntohl(segment->compression);
- new->s_srcaddr = (u32) ((unsigned char *) first_segment) + ntohl(segment->offset);
+ new->s_srcaddr = (u32) ((unsigned char *)first_segment)
+ + ntohl(segment->offset);
new->s_filesz = ntohl(segment->len);
printk(BIOS_DEBUG, " New segment dstaddr 0x%lx memsize 0x%lx srcaddr 0x%lx filesize 0x%lx\n",
new->s_dstaddr, new->s_memsz, new->s_srcaddr, new->s_filesz);
break;
case PAYLOAD_SEGMENT_BSS:
- printk(BIOS_DEBUG, " BSS 0x%p (%d byte)\n", (void *) ntohl((u32) segment->load_addr),
- ntohl(segment->mem_len));
+ printk(BIOS_DEBUG, " BSS 0x%p (%d byte)\n", (void *)
+ (intptr_t)ntohll(segment->load_addr),
+ ntohl(segment->mem_len));
new = malloc(sizeof(*new));
new->s_filesz = 0;
- new->s_dstaddr = ntohl((u32) segment->load_addr);
+ new->s_dstaddr = ntohll(segment->load_addr);
new->s_memsz = ntohl(segment->mem_len);
break;
case PAYLOAD_SEGMENT_ENTRY:
printk(BIOS_DEBUG, " Entry Point 0x%p\n", (void *) ntohl((u32) segment->load_addr));
- *entry = ntohl((u32) segment->load_addr);
+ *entry = ntohll(segment->load_addr);
/* Per definition, a payload always has the entry point
* as last segment. Thus, we use the occurence of the
* entry point as break condition for the loop.
return -1;
}
+ /* We have found another CODE, DATA or BSS segment */
segment++;
- // FIXME: Explain what this is
+ /* Find place where to insert our segment */
for(ptr = head->next; ptr != head; ptr = ptr->next) {
- if (new->s_srcaddr < ntohl((u32) segment->load_addr))
+ if (new->s_srcaddr < ntohll(segment->load_addr))
break;
}
new->prev = ptr->prev;
ptr->prev->next = new;
ptr->prev = new;
-
- /* Order by original program header order */
- new->phdr_next = head;
- new->phdr_prev = head->phdr_prev;
- head->phdr_prev->phdr_next = new;
- head->phdr_prev = new;
}
return 1;
unsigned long bounce_high = lb_end;
for(ptr = head->next; ptr != head; ptr = ptr->next) {
- if (!overlaps_coreboot(ptr)) continue;
+ if (!overlaps_coreboot(ptr))
+ continue;
if (ptr->s_dstaddr + ptr->s_memsz > bounce_high)
bounce_high = ptr->s_dstaddr + ptr->s_memsz;
}
return 0;
break;
}
-#if CONFIG_COMPRESSED_PAYLOAD_NRV2B==1
+#if CONFIG_COMPRESSED_PAYLOAD_NRV2B
case CBFS_COMPRESS_NRV2B: {
printk(BIOS_DEBUG, "using NRV2B\n");
unsigned long unrv2b(u8 *src, u8 *dst, unsigned long *ilen_p);
boot_successful();
printk(BIOS_DEBUG, "Jumping to boot code at %x\n", entry);
- post_code(0xfe);
+ post_code(POST_ENTER_ELF_BOOT);
/* Jump to kernel */
jmp_to_elf_entry((void*)entry, bounce_buffer, bounce_size);
return 1;
- out:
+out:
return 0;
}
+void *cbfs_load_payload(struct lb_memory *lb_mem, const char *name)
+{
+ struct cbfs_payload *payload;
+
+ payload = (struct cbfs_payload *)cbfs_find_file(name, CBFS_TYPE_PAYLOAD);
+ if (payload == NULL)
+ return (void *) -1;
+ printk(BIOS_DEBUG, "Got a payload\n");
+
+ selfboot(lb_mem, payload);
+ printk(BIOS_EMERG, "SELFBOOT RETURNED!\n");
+
+ return (void *) -1;
+}
+