coreboot-v2/util/cbfstool/cbfs-mkpayload.c
<<
>>
Prefs
   1/*
   2 * cbfs-mkpayload
   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#include <arpa/inet.h>
  31
  32#include "common.h"
  33#include "cbfs.h"
  34
  35int parse_elf_to_payload(unsigned char *input, unsigned char **output,
  36                         comp_algo algo)
  37{
  38        Elf32_Phdr *phdr;
  39        Elf32_Ehdr *ehdr;
  40        Elf32_Shdr *shdr;
  41        char *header;
  42        char *strtab;
  43        unsigned char *sptr;
  44        int headers;
  45        int segments = 1;
  46        int isize = 0, osize = 0;
  47        int doffset = 0;
  48        struct cbfs_payload_segment *segs;
  49        int i;
  50
  51        if(!iself(input)){
  52                printf("Fatal error: the payload file is not in ELF format!\n");
  53                exit(1);
  54        }
  55
  56
  57        comp_func_ptr compress = compression_function(algo);
  58        if (!compress)
  59                return -1;
  60
  61        ehdr = (Elf32_Ehdr *) input;
  62        headers = ehdr->e_phnum;
  63        header = (char *)ehdr;
  64
  65        phdr = (Elf32_Phdr *) & (header[ehdr->e_phoff]);
  66        shdr = (Elf32_Shdr *) & (header[ehdr->e_shoff]);
  67
  68        strtab = &header[shdr[ehdr->e_shstrndx].sh_offset];
  69
  70        /* Count the number of headers - look for the .notes.pinfo
  71         * section */
  72
  73        for (i = 0; i < ehdr->e_shnum; i++) {
  74                char *name;
  75
  76                if (i == ehdr->e_shstrndx)
  77                        continue;
  78
  79                if (shdr[i].sh_size == 0)
  80                        continue;
  81
  82                name = (char *)(strtab + shdr[i].sh_name);
  83
  84                if (!strcmp(name, ".note.pinfo")) {
  85                        segments++;
  86                        isize += (unsigned int)shdr[i].sh_size;
  87                }
  88        }
  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        for (i = 0; i < headers; i++) {
  95                if (phdr[i].p_type != PT_LOAD)
  96                        continue;
  97
  98                /* Empty segments are never interesting */
  99                if (phdr[i].p_memsz == 0)
 100                        continue;
 101
 102                isize += phdr[i].p_filesz;
 103
 104                segments++;
 105        }
 106
 107        /* Allocate a block of memory to store the data in */
 108
 109        sptr =
 110            calloc((segments * sizeof(struct cbfs_payload_segment)) + isize, 1);
 111        doffset = (segments * sizeof(struct cbfs_payload_segment));
 112
 113        if (sptr == NULL)
 114                goto err;
 115
 116        segs = (struct cbfs_payload_segment *)sptr;
 117        segments = 0;
 118
 119        for (i = 0; i < ehdr->e_shnum; i++) {
 120                char *name;
 121
 122                if (i == ehdr->e_shstrndx)
 123                        continue;
 124
 125                if (shdr[i].sh_size == 0)
 126                        continue;
 127
 128                name = (char *)(strtab + shdr[i].sh_name);
 129
 130                if (!strcmp(name, ".note.pinfo")) {
 131                        segs[segments].type = PAYLOAD_SEGMENT_PARAMS;
 132                        segs[segments].load_addr = 0;
 133                        segs[segments].len = (unsigned int)shdr[i].sh_size;
 134                        segs[segments].offset = doffset;
 135
 136                        memcpy((unsigned long *)(sptr + doffset),
 137                               &header[shdr[i].sh_offset], shdr[i].sh_size);
 138
 139                        doffset += segs[segments].len;
 140                        osize += segs[segments].len;
 141
 142                        segments++;
 143                }
 144        }
 145
 146        for (i = 0; i < headers; i++) {
 147                if (phdr[i].p_type != PT_LOAD)
 148                        continue;
 149
 150                if (phdr[i].p_memsz == 0)
 151                        continue;
 152
 153                if (phdr[i].p_filesz == 0) {
 154                        segs[segments].type = PAYLOAD_SEGMENT_BSS;
 155                        segs[segments].load_addr =
 156                            (unsigned long long)htonl(phdr[i].p_paddr);
 157                        segs[segments].mem_len =
 158                            (unsigned int)htonl(phdr[i].p_memsz);
 159                        segs[segments].offset = htonl(doffset);
 160
 161                        segments++;
 162                        continue;
 163                }
 164
 165                segs[segments].type = PAYLOAD_SEGMENT_DATA;
 166                segs[segments].load_addr = (unsigned int)htonl(phdr[i].p_paddr);
 167                segs[segments].mem_len = (unsigned int)htonl(phdr[i].p_memsz);
 168                segs[segments].compression = htonl(algo);
 169                segs[segments].offset = htonl(doffset);
 170
 171                int len;
 172                compress((char *)&header[phdr[i].p_offset],
 173                         phdr[i].p_filesz, (char *)(sptr + doffset), &len);
 174                segs[segments].len = htonl(len);
 175
 176                /* If the compressed section is larger, then use the
 177                   original stuff */
 178
 179                if ((unsigned int)len > phdr[i].p_filesz) {
 180                        segs[segments].compression = 0;
 181                        segs[segments].len = htonl(phdr[i].p_filesz);
 182
 183                        memcpy((char *)(sptr + doffset),
 184                               &header[phdr[i].p_offset], phdr[i].p_filesz);
 185                }
 186
 187                doffset += ntohl(segs[segments].len);
 188                osize += ntohl(segs[segments].len);
 189
 190                segments++;
 191        }
 192
 193        segs[segments].type = PAYLOAD_SEGMENT_ENTRY;
 194        segs[segments++].load_addr = (unsigned long long)htonl(ehdr->e_entry);
 195
 196        *output = sptr;
 197
 198        return (segments * sizeof(struct cbfs_payload_segment)) + osize;
 199
 200      err:
 201        return -1;
 202}
 203
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.