blob: 1a52f1093da231662beaa1f22c0d25e29c2532f9 [file] [log] [blame]
/*
* Copyright 2012 Google Inc.
*
* See file CREDITS for list of people who contributed to this
* project.
*
* 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; either version 2 of
* the License, or (at your option) any later version.
*
* 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., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
#include <elf.h>
#include <stdio.h>
#include "base/container_of.h"
#include "base/lzma/lzma.h"
#include "base/xalloc.h"
#include "module/module.h"
#include "module/symbols.h"
#include "module/trampoline/trampoline.h"
int start_module(const void *compressed_image, uint32_t size)
{
// Put the decompressed module at the end of the trampoline.
Elf32_Ehdr *elf = (Elf32_Ehdr *)&_tramp_end;
//XXX This is a hack for now which assumes the decompression area
// ends at the end of the kernel area. Once some sort of global
// memory allocator exists which can keep track of these things
// explicitly (as opposed to by convention) then this can go away.
uint8_t *decomp_end = (uint8_t *)(uintptr_t)(CONFIG_KERNEL_START +
CONFIG_KERNEL_SIZE);
// Decompress the trampoline itself.
uint32_t out_size = ulzman(&_binary_trampoline_start,
(uintptr_t)&_binary_trampoline_size,
(unsigned char *)elf,
decomp_end - &_tramp_end);
if (!out_size) {
printf("Error decompressing trampoline.\n");
return -1;
}
// Expand the trampoline into place.
if (elf_check_header(elf))
return -1;
elf_load(elf);
// Decompress the target image.
out_size = ulzman(compressed_image, size, (unsigned char *)elf,
decomp_end - &_tramp_end);
if (!out_size) {
printf("Error decompressing module.\n");
return -1;
}
// Do some basic checks on the headers.
if (elf_check_header(elf))
return -1;
enter_trampoline(elf);
// We should never actually reach the end of this function.
return 0;
}
static int dc_module_default_start(DcModuleOps *me)
{
DcModule *module = container_of(me, DcModule, ops);
int size = storage_size(module->storage);
if (size < 0)
return 1;
void *image = xmalloc(size);
if (storage_read(module->storage, image, 0, size)) {
free(image);
return 1;
}
start_module(image, size);
free(image);
// If we ever get back to this function, something didn't work.
return 1;
}
DcModule *new_dc_module(StorageOps *storage)
{
DcModule *module = xzalloc(sizeof(*module));
module->ops.start = &dc_module_default_start;
module->storage = storage;
return module;
}