coreboot/util/cbfstool/cbfs-mkstage.c
<<
>>
Prefs
   1/*
   2 * cbfs-mkstage
   3 *
   4 * Copyright (C) 2008 Jordan Crouse <jordan@cosmicpenguin.net>
   5 *               2009 coresystems GmbH
   6 *                 written by Patrick Georgi <patrick.georgi@coresystems.de>
   7 *
   8 * This program is free software; you can redistribute it and/or modify
   9 * it under the terms of the GNU General Public License as published by
  10 * the Free Software Foundation; version 2 of the License.
  11 *
  12 * This program is distributed in the hope that it will be useful,
  13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15 * GNU General Public License for more details.
  16 *
  17 * You should have received a copy of the GNU General Public License
  18 * along with this program; if not, write to the Free Software
  19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA
  20 */
  21
  22#include <stdio.h>
  23#include <stdlib.h>
  24#include <string.h>
  25#include <unistd.h>
  26#include "elf.h"
  27#include <fcntl.h>
  28#include <getopt.h>
  29#include <sys/stat.h>
  30
  31#include "common.h"
  32#include "cbfs.h"
  33
  34unsigned int idemp(unsigned int x)
  35{
  36        return x;
  37}
  38
  39unsigned int swap32(unsigned int x)
  40{
  41        return ((x >> 24) | ((x >> 8) & 0xff00) | ((x << 8) & 0xff0000) |
  42                (x << 24));
  43}
  44
  45unsigned int (*elf32_to_native) (unsigned int) = idemp;
  46
  47/* returns size of result, or -1 if error */
  48int parse_elf_to_stage(unsigned char *input, unsigned char **output,
  49                       comp_algo algo, uint32_t * location)
  50{
  51        Elf32_Phdr *phdr;
  52        Elf32_Ehdr *ehdr = (Elf32_Ehdr *) input;
  53        char *header, *buffer;
  54        unsigned char *out;
  55
  56        int headers;
  57        int i;
  58        struct cbfs_stage *stage;
  59        unsigned int data_start, data_end, mem_end;
  60
  61        int elf_bigendian = 0;
  62        int host_bigendian = 0;
  63
  64        comp_func_ptr compress = compression_function(algo);
  65        if (!compress)
  66                return -1;
  67
  68        if (!iself(input)) {
  69                fprintf(stderr, "E:  The incoming file is not an ELF\n");
  70                return -1;
  71        }
  72
  73        if (ehdr->e_ident[EI_DATA] == ELFDATA2MSB) {
  74                elf_bigendian = 1;
  75        }
  76        char test[4] = "1234";
  77        uint32_t inttest = *(uint32_t *) test;
  78        if (inttest == 0x31323334) {
  79                host_bigendian = 1;
  80        }
  81        if (elf_bigendian != host_bigendian) {
  82                elf32_to_native = swap32;
  83        }
  84
  85        headers = ehdr->e_phnum;
  86        header = (char *)ehdr;
  87
  88        phdr = (Elf32_Phdr *) & header[elf32_to_native(ehdr->e_phoff)];
  89
  90        /* Now, regular headers - we only care about PT_LOAD headers,
  91         * because thats what we're actually going to load
  92         */
  93
  94        data_start = 0xFFFFFFFF;
  95        data_end = 0;
  96        mem_end = 0;
  97
  98        for (i = 0; i < headers; i++) {
  99                unsigned int start, mend, rend;
 100
 101                if (elf32_to_native(phdr[i].p_type) != PT_LOAD)
 102                        continue;
 103
 104                /* Empty segments are never interesting */
 105                if (elf32_to_native(phdr[i].p_memsz) == 0)
 106                        continue;
 107
 108                /* BSS */
 109
 110                start = elf32_to_native(phdr[i].p_paddr);
 111
 112                mend = start + elf32_to_native(phdr[i].p_memsz);
 113                rend = start + elf32_to_native(phdr[i].p_filesz);
 114
 115                if (start < data_start)
 116                        data_start = start;
 117
 118                if (rend > data_end)
 119                        data_end = rend;
 120
 121                if (mend > mem_end)
 122                        mem_end = mend;
 123        }
 124
 125        if (data_start < *location) {
 126                data_start = *location;
 127        }
 128
 129        if (data_end <= data_start) {
 130                fprintf(stderr, "E: data ends before it starts. Make sure the ELF file is correct and resides in ROM space.\n");
 131                exit(1);
 132        }
 133
 134        /* allocate an intermediate buffer for the data */
 135        buffer = calloc(data_end - data_start, 1);
 136
 137        if (buffer == NULL) {
 138                fprintf(stderr, "E: Unable to allocate memory: %m\n");
 139                return -1;
 140        }
 141
 142        /* Copy the file data into the buffer */
 143
 144        for (i = 0; i < headers; i++) {
 145                unsigned int l_start, l_offset = 0;
 146
 147                if (elf32_to_native(phdr[i].p_type) != PT_LOAD)
 148                        continue;
 149
 150                if (elf32_to_native(phdr[i].p_memsz) == 0)
 151                        continue;
 152
 153                l_start = elf32_to_native(phdr[i].p_paddr);
 154                if (l_start < *location) {
 155                        l_offset = *location - l_start;
 156                        l_start = *location;
 157                }
 158
 159                memcpy(buffer + (l_start - data_start),
 160                       &header[elf32_to_native(phdr[i].p_offset)+l_offset],
 161                       elf32_to_native(phdr[i].p_filesz)-l_offset);
 162        }
 163
 164        /* Now make the output buffer */
 165        out = calloc(sizeof(struct cbfs_stage) + data_end - data_start, 1);
 166
 167        if (out == NULL) {
 168                fprintf(stderr, "E: Unable to allocate memory: %m\n");
 169                return -1;
 170        }
 171
 172        stage = (struct cbfs_stage *)out;
 173
 174        stage->load = data_start;
 175        stage->memlen = mem_end - data_start;
 176        stage->compression = algo;
 177        stage->entry = ehdr->e_entry;
 178
 179        compress(buffer, data_end - data_start,
 180                 (char *)(out + sizeof(struct cbfs_stage)), (int *)&stage->len);
 181
 182        *output = out;
 183
 184        if (*location)
 185                *location -= sizeof(struct cbfs_stage);
 186        return sizeof(struct cbfs_stage) + stage->len;
 187}
 188
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.