Eliminate various issues brought up by scan-build.
[coreboot.git] / src / boot / elfboot.c
index 272aee9d7379a2417c773cfe12ee42dc6fba5684..acffb634dac94e643f3989bb9e57e9cd3037eacb 100644 (file)
@@ -1,15 +1,34 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2003 Eric W. Biederman <ebiederm@xmission.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA
+ */
+
 #include <console/console.h>
 #include <part/fallback_boot.h>
 #include <boot/elf.h>
 #include <boot/elf_boot.h>
-#include <boot/linuxbios_tables.h>
+#include <boot/coreboot_tables.h>
 #include <ip_checksum.h>
 #include <stream/read_bytes.h>
 #include <stdint.h>
 #include <stdlib.h>
 #include <string.h>
 
-/* Maximum physical address we can use for the linuxBIOS bounce buffer.
+/* Maximum physical address we can use for the coreboot bounce buffer.
  */
 #ifndef MAX_ADDR
 #define MAX_ADDR -1UL
@@ -76,7 +95,7 @@ int verify_ip_checksum(
                memcpy(n_desc, buff, 2);
        }
        if (checksum != cb->ip_checksum) {
-               printk_err("Image checksum: %04x != computed checksum: %04x\n",
+               printk_err("Image checksum: %04x != computed checksum: %04lx\n",
                        cb->ip_checksum, checksum);
        }
        return checksum == cb->ip_checksum;
@@ -88,16 +107,16 @@ int verify_ip_checksum(
  * a machine, and implementing general relocation is hard.
  *
  * The solution:
- * - Allocate a buffer twice the size of the linuxBIOS image.
- * - Anything that would overwrite linuxBIOS copy into the lower half of
+ * - Allocate a buffer twice the size of the coreboot image.
+ * - Anything that would overwrite coreboot copy into the lower half of
  *   the buffer. 
- * - After loading an ELF image copy linuxBIOS to the upper half of the
+ * - After loading an ELF image copy coreboot to the upper half of the
  *   buffer.
  * - Then jump to the loaded image.
  * 
  * Benefits:
  * - Nearly arbitrary standalone executables can be loaded.
- * - LinuxBIOS is preserved, so it can be returned to.
+ * - Coreboot is preserved, so it can be returned to.
  * - The implementation is still relatively simple,
  *   and much simpler then the general case implemented in kexec.
  * 
@@ -110,7 +129,7 @@ static unsigned long get_bounce_buffer(struct lb_memory *mem)
        unsigned long buffer;
        int i;
        lb_size = (unsigned long)(&_eram_seg - &_ram_seg);
-       /* Double linuxBIOS size so I have somewhere to place a copy to return to */
+       /* Double coreboot size so I have somewhere to place a copy to return to */
        lb_size = lb_size + lb_size;
        mem_entries = (mem->size - sizeof(*mem))/sizeof(mem->map[0]);
        buffer = 0;
@@ -120,14 +139,14 @@ static unsigned long get_bounce_buffer(struct lb_memory *mem)
                unsigned long tbuffer;
                if (mem->map[i].type != LB_MEM_RAM)
                        continue;
-               if (mem->map[i].start > MAX_ADDR)
+               if (unpack_lb64(mem->map[i].start) > MAX_ADDR)
                        continue;
-               if (mem->map[i].size < lb_size)
+               if (unpack_lb64(mem->map[i].size) < lb_size)
                        continue;
-               mstart = mem->map[i].start;
+               mstart = unpack_lb64(mem->map[i].start);
                msize = MAX_ADDR - mstart +1;
-               if (msize > mem->map[i].size)
-                       msize = mem->map[i].size;
+               if (msize > unpack_lb64(mem->map[i].size))
+                       msize = unpack_lb64(mem->map[i].size);
                mend = mstart + msize;
                tbuffer = mend - lb_size;
                if (tbuffer < buffer) 
@@ -144,7 +163,7 @@ static struct verify_callback *process_elf_notes(
 {
        struct verify_callback *cb_chain;
        unsigned char *note, *end;
-       char *program, *version;
+       unsigned char *program, *version;
 
        cb_chain = 0;
        note = header + offset;
@@ -222,11 +241,15 @@ static int valid_area(struct lb_memory *mem, unsigned long buffer,
                uint64_t mstart, mend;
                uint32_t mtype;
                mtype = mem->map[i].type;
-               mstart = mem->map[i].start;
-               mend = mstart + mem->map[i].size;
+               mstart = unpack_lb64(mem->map[i].start);
+               mend = mstart + unpack_lb64(mem->map[i].size);
                if ((mtype == LB_MEM_RAM) && (start < mend) && (end > mstart)) {
                        break;
                }
+               if ((mtype == LB_MEM_TABLE) && (start < mend) && (end > mstart)) {
+                       printk_err("Payload is overwriting Coreboot tables.\n");
+                       break;
+               }
        }
        if (i == mem_entries) {
                printk_err("No matching ram area found for range:\n");
@@ -236,8 +259,8 @@ static int valid_area(struct lb_memory *mem, unsigned long buffer,
                        uint64_t mstart, mend;
                        uint32_t mtype;
                        mtype = mem->map[i].type;
-                       mstart = mem->map[i].start;
-                       mend = mstart + mem->map[i].size;
+                       mstart = unpack_lb64(mem->map[i].start);
+                       mend = mstart + unpack_lb64(mem->map[i].size);
                        printk_err("  [0x%016lx, 0x%016lx) %s\n",
                                (unsigned long)mstart, 
                                (unsigned long)mend, 
@@ -251,7 +274,7 @@ static int valid_area(struct lb_memory *mem, unsigned long buffer,
 
 static void relocate_segment(unsigned long buffer, struct segment *seg)
 {
-       /* Modify all segments that want to load onto linuxBIOS
+       /* Modify all segments that want to load onto coreboot
         * to load onto the bounce buffer instead.
         */
        unsigned long lb_start = (unsigned long)&_ram_seg;
@@ -264,7 +287,7 @@ static void relocate_segment(unsigned long buffer, struct segment *seg)
        start = seg->s_addr;
        middle = start + seg->s_filesz;
        end = start + seg->s_memsz;
-       /* I don't conflict with linuxBIOS so get out of here */
+       /* I don't conflict with coreboot so get out of here */
        if ((end <= lb_start) || (start >= lb_end))
                return;
 
@@ -272,7 +295,7 @@ static void relocate_segment(unsigned long buffer, struct segment *seg)
                start, middle, end);
 
        /* Slice off a piece at the beginning
-        * that doesn't conflict with linuxBIOS.
+        * that doesn't conflict with coreboot.
         */
        if (start < lb_start) {
                struct segment *new;
@@ -311,7 +334,7 @@ static void relocate_segment(unsigned long buffer, struct segment *seg)
        }
        
        /* Slice off a piece at the end 
-        * that doesn't conflict with linuxBIOS 
+        * that doesn't conflict with coreboot 
         */
        if (end > lb_end) {
                unsigned long len = lb_end - start;
@@ -339,9 +362,6 @@ static void relocate_segment(unsigned long buffer, struct segment *seg)
                seg->phdr_next->phdr_prev = new;
                seg->phdr_next = new;
 
-               /* compute the new value of end */
-               end = start + len;
-               
                printk_spew("   late: [0x%016lx, 0x%016lx, 0x%016lx)\n", 
                        new->s_addr, 
                        new->s_addr + new->s_filesz,
@@ -440,6 +460,10 @@ static int load_elf_segments(
                end = dest + ptr->s_memsz;
                middle = dest + ptr->s_filesz;
                start_offset = ptr->s_offset;
+               /* Ignore s_offset if I have a pure bss segment */
+               if (ptr->s_filesz == 0) {
+                       start_offset = offset;
+               }
                
                printk_spew("[ 0x%016lx, %016lx, 0x%016lx) <- %016lx\n",
                        (unsigned long)dest,
@@ -460,7 +484,7 @@ static int load_elf_segments(
                skip_bytes = start_offset - offset;
                if (skip_bytes && 
                        ((result = stream_skip(skip_bytes)) != skip_bytes)) {
-                       printk_err("ERROR: Skip of %ld bytes skiped %ld bytes\n",
+                       printk_err("ERROR: Skip of %ld bytes skipped %ld bytes\n",
                                skip_bytes, result);
                        goto out;
                }
@@ -492,7 +516,7 @@ static int load_elf_segments(
                /* Zero the extra bytes between middle & end */
                if (middle < end) {
                        printk_debug("Clearing Segment: addr: 0x%016lx memsz: 0x%016lx\n",
-                               (unsigned long)middle, end - middle);
+                               (unsigned long)middle, (unsigned long)(end - middle));
                        
                        /* Zero the extra bytes */
                        memset(middle, 0, end - middle);
@@ -541,7 +565,7 @@ int elfload(struct lb_memory *mem,
        struct verify_callback *cb_chain;
        unsigned long bounce_buffer;
 
-       /* Find a bounce buffer so I can load to linuxBIOS's current location */
+       /* 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");
@@ -582,7 +606,7 @@ int elfload(struct lb_memory *mem,
        /* Reset to booting from this image as late as possible */
        boot_successful();
 
-       printk_debug("Jumping to boot code at 0x%x\n", entry);
+       printk_debug("Jumping to boot code at %p\n", entry);
        post_code(0xfe);
 
        /* Jump to kernel */
@@ -601,11 +625,7 @@ int elfboot(struct lb_memory *mem)
        int i, result;
 
        result = 0;
-       printk_info("\n");
-       printk_info("Welcome to %s, the open sourced starter.\n", BOOTLOADER);
-       printk_info("January 2002, Eric Biederman.\n");
-       printk_info("Version %s\n", BOOTLOADER_VERSION);
-       printk_info("\n");
+       printk_debug("\nelfboot: Attempting to load payload.\n");
        post_code(0xf8);
 
        if (stream_init() < 0) {
@@ -623,10 +643,10 @@ int elfboot(struct lb_memory *mem)
        for(i = 0; i < ELF_HEAD_SIZE - (sizeof(Elf_ehdr) + sizeof(Elf_phdr)); i+=16) {
                ehdr = (Elf_ehdr *)(&header[i]);
                if (memcmp(ehdr->e_ident, ELFMAG, 4) != 0) {
-                       printk_spew("NO header at %d\n", i);
+                       printk_debug("No header at %d\n", i);
                        continue;
                }
-               printk_debug("Found ELF candiate at offset %d\n", i);
+               printk_debug("Found ELF candidate at offset %d\n", i);
                /* Sanity check the elf header */
                if ((ehdr->e_type == ET_EXEC) &&
                        elf_check_arch(ehdr) &&
@@ -642,12 +662,12 @@ int elfboot(struct lb_memory *mem)
                }
                ehdr = 0;
        }
-       printk_spew("header_offset is %d\n", header_offset);
+       printk_debug("header_offset is %d\n", header_offset);
        if (header_offset == -1) {
                goto out;
        }
 
-       printk_spew("Try to load at offset 0x%x\n", header_offset);
+       printk_debug("Try to load at offset 0x%x\n", header_offset);
        result = elfload(mem, 
                header + header_offset , ELF_HEAD_SIZE - header_offset);
  out:
@@ -655,7 +675,7 @@ int elfboot(struct lb_memory *mem)
                /* Shutdown the stream device */
                stream_fini();
 
-               printk_err("Cannot Load ELF Image\n");
+               printk_err("Can not load ELF Image.\n");
 
                post_code(0xff);
        }