qemu/hw/misc/blob-loader.c
<<
>>
Prefs
   1/*
   2 * generic blob loader
   3 *
   4 * Copyright (C) 2014 Li Guang
   5 * Written by Li Guang <lig.fnst@cn.fujitsu.com>
   6 *
   7 * This program is free software; you can redistribute it and/or modify it
   8 * under the terms of the GNU General Public License as published by the
   9 * Free Software Foundation; either version 2 of the License, or
  10 * (at your option) any later version.
  11 *
  12 * This program is distributed in the hope that it will be useful, but WITHOUT
  13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
  15 * for more details.
  16 */
  17
  18#include "sysemu/sysemu.h"
  19#include "config.h"
  20#include "hw/sysbus.h"
  21#include "hw/devices.h"
  22#include "hw/loader.h"
  23#include "hw/misc/blob-loader.h"
  24#include "qemu/error-report.h"
  25#include "sysemu/dma.h"
  26#include "hw/loader.h"
  27#include "elf.h"
  28
  29#define BLOB_LOADER_CPU_NONE 0xff
  30
  31static Property blob_loader_props[] = {
  32    DEFINE_PROP_UINT64("addr", BlobLoaderState, addr, 0),
  33    DEFINE_PROP_UINT64("data", BlobLoaderState, data, 0),
  34    DEFINE_PROP_UINT8("data-len", BlobLoaderState, data_len, 0),
  35    DEFINE_PROP_UINT8("cpu", BlobLoaderState, cpu_nr, BLOB_LOADER_CPU_NONE),
  36    DEFINE_PROP_BOOL("force-raw", BlobLoaderState, force_raw, false),
  37    DEFINE_PROP_STRING("file", BlobLoaderState, file),
  38    DEFINE_PROP_END_OF_LIST(),
  39};
  40
  41extern AddressSpace *loader_as;
  42
  43static void blob_loader_realize(DeviceState *dev, Error **errp)
  44{
  45    BlobLoaderState *s = BLOB_LOADER(dev);
  46    int size = 0;
  47    hwaddr entry;
  48
  49    if (s->cpu_nr != BLOB_LOADER_CPU_NONE) {
  50        CPUState *cs = first_cpu;
  51        int cpu_nr = s->cpu_nr;
  52
  53        while (cs && cpu_nr) {
  54            cs = CPU_NEXT(cs);
  55            cpu_nr--;
  56        }
  57        if (!cs) {
  58            error_setg(errp, "Specified boot cpu #%d is non existant",
  59                       s->cpu_nr);
  60            return;
  61        }
  62        s->cpu = cs;
  63    }
  64
  65    if (s->cpu) {
  66        loader_as = s->cpu->as;
  67    }
  68
  69    if (s->file) {
  70        /* FIXME: Make work on BE */
  71        if (s->force_raw) {
  72            goto do_raw;
  73        }
  74        size = load_elf(s->file, NULL, NULL, &entry, NULL, NULL, 0,
  75                        ELF_MACHINE, 0);
  76        /* If it wasn't an ELF image, try an u-boot image. */
  77        if (size < 0) {
  78            size = load_uimage(s->file, &entry, NULL, NULL, NULL, NULL);
  79        }
  80        /* Not an ELF image nor a u-boot image, try a RAW image. */
  81do_raw:
  82        if (size < 0) {
  83            /* FIXME: sanitize size limit */
  84            size = load_image_targphys(s->file, s->addr, 0);
  85        } else {
  86            s->addr = entry;
  87        }
  88        if (size < 0) {
  89            error_setg(errp, "Cannot load specified image %s", s->file);
  90            return;
  91        }
  92    }
  93
  94    loader_as = NULL;
  95
  96}
  97
  98static void blob_loader_reset(DeviceState *dev)
  99{
 100    BlobLoaderState *s = BLOB_LOADER(dev);
 101
 102    if (s->cpu) {
 103        CPUClass *cc = CPU_GET_CLASS(s->cpu);
 104        cpu_reset(s->cpu);
 105        cc->set_pc(s->cpu, s->addr);
 106        cpu_halt_reset_common(s->cpu, NULL, false, true);
 107    }
 108    /* Probably only works on LE */
 109    if (s->data_len) {
 110        dma_memory_write((s->cpu ? s->cpu : first_cpu)->as, s->addr, &s->data,
 111                         s->data_len);
 112    }
 113}
 114
 115static void blob_loader_class_init(ObjectClass *klass, void *data)
 116{
 117    DeviceClass *dc = DEVICE_CLASS(klass);
 118
 119    dc->reset = blob_loader_reset;
 120    dc->realize = blob_loader_realize;
 121    dc->props = blob_loader_props;
 122    dc->desc = "blob loader";
 123}
 124
 125static TypeInfo blob_loader_info = {
 126    .name = TYPE_BLOB_LOADER,
 127    .parent = TYPE_DEVICE,
 128    .instance_size = sizeof(BlobLoaderState),
 129    .class_init = blob_loader_class_init,
 130};
 131
 132static void blob_loader_register_type(void)
 133{
 134    type_register_static(&blob_loader_info);
 135}
 136
 137type_init(blob_loader_register_type)
 138