コード例 #1
0
ファイル: aspeed.c プロジェクト: alistair23/qemu
static void write_boot_rom(DriveInfo *dinfo, hwaddr addr, size_t rom_size,
                           Error **errp)
{
    BlockBackend *blk = blk_by_legacy_dinfo(dinfo);
    uint8_t *storage;
    int64_t size;

    /* The block backend size should have already been 'validated' by
     * the creation of the m25p80 object.
     */
    size = blk_getlength(blk);
    if (size <= 0) {
        error_setg(errp, "failed to get flash size");
        return;
    }

    if (rom_size > size) {
        rom_size = size;
    }

    storage = g_new0(uint8_t, rom_size);
    if (blk_pread(blk, 0, storage, rom_size) < 0) {
        error_setg(errp, "failed to read the initial flash content");
        return;
    }

    rom_add_blob_fixed("aspeed.boot_rom", storage, rom_size, addr);
    g_free(storage);
}
コード例 #2
0
ファイル: exynos4210.c プロジェクト: L0op/qemu
void exynos4210_write_secondary(ARMCPU *cpu,
        const struct arm_boot_info *info)
{
    int n;
    uint32_t smpboot[] = {
        0xe59f3034, /* ldr r3, External gic_cpu_if */
        0xe59f2034, /* ldr r2, Internal gic_cpu_if */
        0xe59f0034, /* ldr r0, startaddr */
        0xe3a01001, /* mov r1, #1 */
        0xe5821000, /* str r1, [r2] */
        0xe5831000, /* str r1, [r3] */
        0xe3a010ff, /* mov r1, #0xff */
        0xe5821004, /* str r1, [r2, #4] */
        0xe5831004, /* str r1, [r3, #4] */
        0xf57ff04f, /* dsb */
        0xe320f003, /* wfi */
        0xe5901000, /* ldr     r1, [r0] */
        0xe1110001, /* tst     r1, r1 */
        0x0afffffb, /* beq     <wfi> */
        0xe12fff11, /* bx      r1 */
        EXYNOS4210_EXT_GIC_CPU_BASE_ADDR,
        0,          /* gic_cpu_if: base address of Internal GIC CPU interface */
        0           /* bootreg: Boot register address is held here */
    };
    smpboot[ARRAY_SIZE(smpboot) - 1] = info->smp_bootreg_addr;
    smpboot[ARRAY_SIZE(smpboot) - 2] = info->gic_cpu_if_addr;
    for (n = 0; n < ARRAY_SIZE(smpboot); n++) {
        smpboot[n] = tswap32(smpboot[n]);
    }
    rom_add_blob_fixed("smpboot", smpboot, sizeof(smpboot),
                       info->smp_loader_start);
}
コード例 #3
0
ファイル: highbank.c プロジェクト: CRYP706URU/pyrebox
static void hb_write_secondary(ARMCPU *cpu, const struct arm_boot_info *info)
{
    int n;
    uint32_t smpboot[] = {
        0xee100fb0, /* mrc p15, 0, r0, c0, c0, 5 - read current core id */
        0xe210000f, /* ands r0, r0, #0x0f */
        0xe3a03040, /* mov r3, #0x40 - jump address is 0x40 + 0x10 * core id */
        0xe0830200, /* add r0, r3, r0, lsl #4 */
        0xe59f2024, /* ldr r2, privbase */
        0xe3a01001, /* mov r1, #1 */
        0xe5821100, /* str r1, [r2, #256] - set GICC_CTLR.Enable */
        0xe3a010ff, /* mov r1, #0xff */
        0xe5821104, /* str r1, [r2, #260] - set GICC_PMR.Priority to 0xff */
        0xf57ff04f, /* dsb */
        0xe320f003, /* wfi */
        0xe5901000, /* ldr     r1, [r0] */
        0xe1110001, /* tst     r1, r1 */
        0x0afffffb, /* beq     <wfi> */
        0xe12fff11, /* bx      r1 */
        MPCORE_PERIPHBASE   /* privbase: MPCore peripheral base address.  */
    };
    for (n = 0; n < ARRAY_SIZE(smpboot); n++) {
        smpboot[n] = tswap32(smpboot[n]);
    }
    rom_add_blob_fixed("smpboot", smpboot, sizeof(smpboot), SMP_BOOT_ADDR);
}
コード例 #4
0
ファイル: highbank.c プロジェクト: dota1923/qemu
static void hb_write_board_setup(ARMCPU *cpu,
                                 const struct arm_boot_info *info)
{
    int n;
    uint32_t board_setup_blob[] = {
        /* MVBAR_ADDR */
        /* Default unimplemented and unused vectors to spin. Makes it
         * easier to debug (as opposed to the CPU running away).
         */
        0xeafffffe, /* notused1: b notused */
        0xeafffffe, /* notused2: b notused */
        0xe1b0f00e, /* smc: movs pc, lr - exception return */
        0xeafffffe, /* prefetch_abort: b prefetch_abort */
        0xeafffffe, /* data_abort: b data_abort */
        0xeafffffe, /* notused3: b notused3 */
        0xeafffffe, /* irq: b irq */
        0xeafffffe, /* fiq: b fiq */
#define BOARD_SETUP_ADDR (MVBAR_ADDR + 8 * sizeof(uint32_t))
        0xe3000000 + ARMV7_IMM16(MVBAR_ADDR), /* movw r0, MVBAR_ADDR */
        0xee0c0f30, /* mcr p15, 0, r0, c12, c0, 1 - set MVBAR */
        0xee110f11, /* mrc p15, 0, r0, c1 , c1, 0 - get SCR */
        0xe3810001, /* orr r0, #1 - set NS */
        0xee010f11, /* mcr p15, 0, r0, c1 , c1, 0 - set SCR */
        0xe1600070, /* smc - go to monitor mode to flush NS change */
        0xe12fff1e, /* bx lr - return to caller */
    };
    for (n = 0; n < ARRAY_SIZE(board_setup_blob); n++) {
        board_setup_blob[n] = tswap32(board_setup_blob[n]);
    }
    rom_add_blob_fixed("board-setup", board_setup_blob,
                       sizeof(board_setup_blob), MVBAR_ADDR);
}
コード例 #5
0
ファイル: loader-fit.c プロジェクト: 8tab/qemu
static int fit_load_kernel(const struct fit_loader *ldr, const void *itb,
                           int cfg, void *opaque, hwaddr *pend)
{
    const char *name;
    const void *data;
    const void *load_data;
    hwaddr load_addr, entry_addr;
    int img_off, err;
    size_t sz;
    int ret;

    name = fdt_getprop(itb, cfg, "kernel", NULL);
    if (!name) {
        error_printf("no kernel specified by FIT configuration\n");
        return -EINVAL;
    }

    load_data = data = fit_load_image_alloc(itb, name, &img_off, &sz);
    if (!data) {
        error_printf("unable to load kernel image from FIT\n");
        return -EINVAL;
    }

    err = fit_image_addr(itb, img_off, "load", &load_addr);
    if (err) {
        error_printf("unable to read kernel load address from FIT\n");
        ret = err;
        goto out;
    }

    err = fit_image_addr(itb, img_off, "entry", &entry_addr);
    if (err) {
        error_printf("unable to read kernel entry address from FIT\n");
        ret = err;
        goto out;
    }

    if (ldr->kernel_filter) {
        load_data = ldr->kernel_filter(opaque, data, &load_addr, &entry_addr);
    }

    if (pend) {
        *pend = load_addr + sz;
    }

    load_addr = ldr->addr_to_phys(opaque, load_addr);
    rom_add_blob_fixed(name, load_data, sz, load_addr);

    ret = 0;
out:
    g_free((void *) data);
    if (data != load_data) {
        g_free((void *) load_data);
    }
    return ret;
}
コード例 #6
0
ファイル: ppc440_bamboo.c プロジェクト: h3likaon/qemu-kvm
static int bamboo_load_device_tree(target_phys_addr_t addr,
                                   uint32_t ramsize,
                                   target_phys_addr_t initrd_base,
                                   target_phys_addr_t initrd_size,
                                   const char *kernel_cmdline)
{
    int ret = -1;
#ifdef CONFIG_FDT
    uint32_t mem_reg_property[] = { 0, 0, ramsize };
    char *filename;
    int fdt_size;
    void *fdt;

    filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, BINARY_DEVICE_TREE_FILE);
    if (!filename) {
        goto out;
    }
    fdt = load_device_tree(filename, &fdt_size);
    g_free(filename);
    if (fdt == NULL) {
        goto out;
    }

    /* Manipulate device tree in memory. */

    ret = qemu_devtree_setprop(fdt, "/memory", "reg", mem_reg_property,
                               sizeof(mem_reg_property));
    if (ret < 0)
        fprintf(stderr, "couldn't set /memory/reg\n");

    ret = qemu_devtree_setprop_cell(fdt, "/chosen", "linux,initrd-start",
                                    initrd_base);
    if (ret < 0)
        fprintf(stderr, "couldn't set /chosen/linux,initrd-start\n");

    ret = qemu_devtree_setprop_cell(fdt, "/chosen", "linux,initrd-end",
                                    (initrd_base + initrd_size));
    if (ret < 0)
        fprintf(stderr, "couldn't set /chosen/linux,initrd-end\n");

    ret = qemu_devtree_setprop_string(fdt, "/chosen", "bootargs",
                                      kernel_cmdline);
    if (ret < 0)
        fprintf(stderr, "couldn't set /chosen/bootargs\n");

    if (kvm_enabled())
        kvmppc_fdt_update(fdt);

    ret = rom_add_blob_fixed(BINARY_DEVICE_TREE_FILE, fdt, fdt_size, addr);
    g_free(fdt);

out:
#endif

    return ret;
}
コード例 #7
0
ファイル: xilinx_zynq.c プロジェクト: L0op/qemu
static void zynq_write_secondary_boot(ARMCPU *cpu,
                                      const struct arm_boot_info *info)
{
    int n;

    for (n = 0; n < ARRAY_SIZE(zynq_smpboot); n++) {
        zynq_smpboot[n] = tswap32(zynq_smpboot[n]);
    }
    rom_add_blob_fixed("smpboot", zynq_smpboot, sizeof(zynq_smpboot),
                       SMP_BOOT_ADDR);
}
コード例 #8
0
ファイル: loader-fit.c プロジェクト: 8tab/qemu
static int fit_load_fdt(const struct fit_loader *ldr, const void *itb,
                        int cfg, void *opaque, const void *match_data,
                        hwaddr kernel_end)
{
    const char *name;
    const void *data;
    const void *load_data;
    hwaddr load_addr;
    int img_off, err;
    size_t sz;
    int ret;

    name = fdt_getprop(itb, cfg, "fdt", NULL);
    if (!name) {
        return 0;
    }

    load_data = data = fit_load_image_alloc(itb, name, &img_off, &sz);
    if (!data) {
        error_printf("unable to load FDT image from FIT\n");
        return -EINVAL;
    }

    err = fit_image_addr(itb, img_off, "load", &load_addr);
    if (err == -ENOENT) {
        load_addr = ROUND_UP(kernel_end, 64 * K_BYTE) + (10 * M_BYTE);
    } else if (err) {
        ret = err;
        goto out;
    }

    if (ldr->fdt_filter) {
        load_data = ldr->fdt_filter(opaque, data, match_data, &load_addr);
    }

    load_addr = ldr->addr_to_phys(opaque, load_addr);
    sz = fdt_totalsize(load_data);
    rom_add_blob_fixed(name, load_data, sz, load_addr);

    ret = 0;
out:
    g_free((void *) data);
    if (data != load_data) {
        g_free((void *) load_data);
    }
    return ret;
}
コード例 #9
0
ファイル: xilinx_zynq.c プロジェクト: sukadev/qemu
static void zynq_write_board_setup(ARMCPU *cpu,
                                   const struct arm_boot_info *info)
{
    int n;
    uint32_t board_setup_blob[] = {
        0xe3a004f8, /* mov r0, #0xf8000000 */
        SLCR_WRITE(SLCR_UNLOCK_OFFSET, SLCR_XILINX_UNLOCK_KEY),
        SLCR_WRITE(SLCR_ARM_PLL_OFFSET, 0x00014008),
        SLCR_WRITE(SLCR_LOCK_OFFSET, SLCR_XILINX_LOCK_KEY),
        0xe12fff1e, /* bx lr */
    };
    for (n = 0; n < ARRAY_SIZE(board_setup_blob); n++) {
        board_setup_blob[n] = tswap32(board_setup_blob[n]);
    }
    rom_add_blob_fixed("board-setup", board_setup_blob,
                       sizeof(board_setup_blob), BOARD_SETUP_ADDR);
}
コード例 #10
0
ファイル: highbank.c プロジェクト: MrPavel3243/limbo-android
static void hb_write_secondary(CPUARMState *env, const struct arm_boot_info *info)
{
    int n;
    uint32_t smpboot[] = {
        0xee100fb0, /* mrc p15, 0, r0, c0, c0, 5 - read current core id */
        0xe210000f, /* ands r0, r0, #0x0f */
        0xe3a03040, /* mov r3, #0x40 - jump address is 0x40 + 0x10 * core id */
        0xe0830200, /* add r0, r3, r0, lsl #4 */
        0xe59f2018, /* ldr r2, privbase */
        0xe3a01001, /* mov r1, #1 */
        0xe5821100, /* str r1, [r2, #256] */
        0xe320f003, /* wfi */
        0xe5901000, /* ldr     r1, [r0] */
        0xe1110001, /* tst     r1, r1 */
        0x0afffffb, /* beq     <wfi> */
        0xe12fff11, /* bx      r1 */
        GIC_BASE_ADDR      /* privbase: gic address.  */
    };
    for (n = 0; n < ARRAY_SIZE(smpboot); n++) {
        smpboot[n] = tswap32(smpboot[n]);
    }
    rom_add_blob_fixed("smpboot", smpboot, sizeof(smpboot), SMP_BOOT_ADDR);
}
コード例 #11
0
static int mpc8544_load_device_tree(CPUPPCState *env,
                                    target_phys_addr_t addr,
                                    uint32_t ramsize,
                                    target_phys_addr_t initrd_base,
                                    target_phys_addr_t initrd_size,
                                    const char *kernel_cmdline)
{
    int ret = -1;
#ifdef CONFIG_FDT
    uint32_t mem_reg_property[] = {0, cpu_to_be32(ramsize)};
    char *filename;
    int fdt_size;
    void *fdt;
    uint8_t hypercall[16];
    uint32_t clock_freq = 400000000;
    uint32_t tb_freq = 400000000;
    int i;

    filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, BINARY_DEVICE_TREE_FILE);
    if (!filename) {
        goto out;
    }
    fdt = load_device_tree(filename, &fdt_size);
    g_free(filename);
    if (fdt == NULL) {
        goto out;
    }

    /* Manipulate device tree in memory. */
    ret = qemu_devtree_setprop(fdt, "/memory", "reg", mem_reg_property,
                               sizeof(mem_reg_property));
    if (ret < 0)
        fprintf(stderr, "couldn't set /memory/reg\n");

    if (initrd_size) {
        ret = qemu_devtree_setprop_cell(fdt, "/chosen", "linux,initrd-start",
                                        initrd_base);
        if (ret < 0) {
            fprintf(stderr, "couldn't set /chosen/linux,initrd-start\n");
        }

        ret = qemu_devtree_setprop_cell(fdt, "/chosen", "linux,initrd-end",
                                        (initrd_base + initrd_size));
        if (ret < 0) {
            fprintf(stderr, "couldn't set /chosen/linux,initrd-end\n");
        }
    }

    ret = qemu_devtree_setprop_string(fdt, "/chosen", "bootargs",
                                      kernel_cmdline);
    if (ret < 0)
        fprintf(stderr, "couldn't set /chosen/bootargs\n");

    if (kvm_enabled()) {
        /* Read out host's frequencies */
        clock_freq = kvmppc_get_clockfreq();
        tb_freq = kvmppc_get_tbfreq();

        /* indicate KVM hypercall interface */
        qemu_devtree_setprop_string(fdt, "/hypervisor", "compatible",
                                    "linux,kvm");
        kvmppc_get_hypercall(env, hypercall, sizeof(hypercall));
        qemu_devtree_setprop(fdt, "/hypervisor", "hcall-instructions",
                             hypercall, sizeof(hypercall));
    }

    /* We need to generate the cpu nodes in reverse order, so Linux can pick
       the first node as boot node and be happy */
    for (i = smp_cpus - 1; i >= 0; i--) {
        char cpu_name[128];
        uint64_t cpu_release_addr = cpu_to_be64(MPC8544_SPIN_BASE + (i * 0x20));

        for (env = first_cpu; env != NULL; env = env->next_cpu) {
            if (env->cpu_index == i) {
                break;
            }
        }

        if (!env) {
            continue;
        }

        snprintf(cpu_name, sizeof(cpu_name), "/cpus/PowerPC,8544@%x", env->cpu_index);
        qemu_devtree_add_subnode(fdt, cpu_name);
        qemu_devtree_setprop_cell(fdt, cpu_name, "clock-frequency", clock_freq);
        qemu_devtree_setprop_cell(fdt, cpu_name, "timebase-frequency", tb_freq);
        qemu_devtree_setprop_string(fdt, cpu_name, "device_type", "cpu");
        qemu_devtree_setprop_cell(fdt, cpu_name, "reg", env->cpu_index);
        qemu_devtree_setprop_cell(fdt, cpu_name, "d-cache-line-size",
                                  env->dcache_line_size);
        qemu_devtree_setprop_cell(fdt, cpu_name, "i-cache-line-size",
                                  env->icache_line_size);
        qemu_devtree_setprop_cell(fdt, cpu_name, "d-cache-size", 0x8000);
        qemu_devtree_setprop_cell(fdt, cpu_name, "i-cache-size", 0x8000);
        qemu_devtree_setprop_cell(fdt, cpu_name, "bus-frequency", 0);
        if (env->cpu_index) {
            qemu_devtree_setprop_string(fdt, cpu_name, "status", "disabled");
            qemu_devtree_setprop_string(fdt, cpu_name, "enable-method", "spin-table");
            qemu_devtree_setprop(fdt, cpu_name, "cpu-release-addr",
                                 &cpu_release_addr, sizeof(cpu_release_addr));
        } else {
            qemu_devtree_setprop_string(fdt, cpu_name, "status", "okay");
        }
    }

    ret = rom_add_blob_fixed(BINARY_DEVICE_TREE_FILE, fdt, fdt_size, addr);
    g_free(fdt);

out:
#endif

    return ret;
}
コード例 #12
0
ファイル: xbox.c プロジェクト: JayFoxRox/xqemu
static void xbox_flash_init(MemoryRegion *rom_memory)
{
    char *filename;
    int bios_size;
    int bootrom_size;

    MemoryRegion *bios;
    MemoryRegion *map_bios;

    uint32_t map_loc;
    int rc, fd = -1;

    char *bios_data;

    /* Locate BIOS ROM image */
    if (bios_name == NULL) {
        bios_name = "bios.bin";
    }

    filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
    if (filename) {
        bios_size = get_image_size(filename);
    } else {
        bios_size = -1;
    }
    if (bios_size <= 0 ||
        (bios_size % 65536) != 0) {
        goto bios_error;
    }

    /* Read BIOS ROM into memory */
    bios_data = g_malloc(bios_size);
    assert(bios_data != NULL);
    fd = open(filename, O_RDONLY | O_BINARY);
    assert(fd >= 0);
    rc = read(fd, bios_data, bios_size);
    assert(rc == bios_size);
    close(fd);
    g_free(filename);

    /* XBOX_FIXME: What follows is a big hack to overlay the MCPX ROM on the
     * top 512 bytes of the ROM region. This differs from original XQEMU
     * sources which copied it in at lpc init; new QEMU seems to be different
     * now in that the BIOS images supplied to rom_add_file_fixed will be
     * loaded *after* lpc init is called, so the MCPX ROM would get
     * overwritten. Instead, let's just map it in right here while we map in
     * BIOS.
     *
     * Anyway it behaves the same as before--that is, wrongly. Really, we
     * should let the CPU execute from MMIO emulating the TSOP access with
     * bootrom overlay being controlled by the magic bit..but this is "good
     * enough" for now ;).
     */

    /* Locate and overlay MCPX ROM image into new copy of BIOS if provided */
    const char *bootrom_file = object_property_get_str(qdev_get_machine(),
                                                       "bootrom", NULL);

    if ((bootrom_file != NULL) && *bootrom_file) {
        filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bootrom_file);
        assert(filename);

        bootrom_size = get_image_size(filename);
        if (bootrom_size != 512) {
            fprintf(stderr, "MCPX bootrom should be 512 bytes, got %d\n",
                    bootrom_size);
            exit(1);
            return;
        }

        /* Read in MCPX ROM over last 512 bytes of BIOS data */
        fd = open(filename, O_RDONLY | O_BINARY);
        assert(fd >= 0);
        rc = read(fd, &bios_data[bios_size - bootrom_size], bootrom_size);
        assert(rc == bootrom_size);
        close(fd);
        g_free(filename);
    }

    /* Create BIOS region */
    bios = g_malloc(sizeof(*bios));
    assert(bios != NULL);
    memory_region_init_ram(bios, NULL, "xbox.bios", bios_size, &error_fatal);
    memory_region_set_readonly(bios, true);
    rom_add_blob_fixed("xbox.bios", bios_data, bios_size,
                       (uint32_t)(-2 * bios_size));

    /* Assuming bios_data will be needed for duration of execution
     * so no free(bios) here.
     */

    /* Mirror ROM from 0xff000000 - 0xffffffff */
    for (map_loc = (uint32_t)(-bios_size);
         map_loc >= 0xff000000;
         map_loc -= bios_size) {
        map_bios = g_malloc(sizeof(*map_bios));
        memory_region_init_alias(map_bios, NULL, "pci-bios", bios, 0, bios_size);
        memory_region_add_subregion(rom_memory, map_loc, map_bios);
        memory_region_set_readonly(map_bios, true);
    }

    return;

bios_error:
    fprintf(stderr, "qemu: could not load xbox BIOS '%s'\n", bios_name);
    exit(1);
}
コード例 #13
0
ファイル: mips_r4k.c プロジェクト: AmesianX/qemu-kvm
static int64_t load_kernel(void)
{
    int64_t entry, kernel_high;
    long kernel_size, initrd_size, params_size;
    ram_addr_t initrd_offset;
    uint32_t *params_buf;
    int big_endian;

#ifdef TARGET_WORDS_BIGENDIAN
    big_endian = 1;
#else
    big_endian = 0;
#endif
    kernel_size = load_elf(loaderparams.kernel_filename, cpu_mips_kseg0_to_phys,
                           NULL, (uint64_t *)&entry, NULL,
                           (uint64_t *)&kernel_high, big_endian,
                           ELF_MACHINE, 1);
    if (kernel_size >= 0) {
        if ((entry & ~0x7fffffffULL) == 0x80000000)
            entry = (int32_t)entry;
    } else {
        fprintf(stderr, "qemu: could not load kernel '%s'\n",
                loaderparams.kernel_filename);
        exit(1);
    }

    /* load initrd */
    initrd_size = 0;
    initrd_offset = 0;
    if (loaderparams.initrd_filename) {
        initrd_size = get_image_size (loaderparams.initrd_filename);
        if (initrd_size > 0) {
            initrd_offset = (kernel_high + ~TARGET_PAGE_MASK) & TARGET_PAGE_MASK;
            if (initrd_offset + initrd_size > ram_size) {
                fprintf(stderr,
                        "qemu: memory too small for initial ram disk '%s'\n",
                        loaderparams.initrd_filename);
                exit(1);
            }
            initrd_size = load_image_targphys(loaderparams.initrd_filename,
                                              initrd_offset,
                                              ram_size - initrd_offset);
        }
        if (initrd_size == (target_ulong) -1) {
            fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
                    loaderparams.initrd_filename);
            exit(1);
        }
    }

    /* Store command line.  */
    params_size = 264;
    params_buf = qemu_malloc(params_size);

    params_buf[0] = tswap32(ram_size);
    params_buf[1] = tswap32(0x12345678);

    if (initrd_size > 0) {
        snprintf((char *)params_buf + 8, 256, "rd_start=0x%" PRIx64 " rd_size=%li %s",
                 cpu_mips_phys_to_kseg0(NULL, initrd_offset),
                 initrd_size, loaderparams.kernel_cmdline);
    } else {
        snprintf((char *)params_buf + 8, 256, "%s", loaderparams.kernel_cmdline);
    }

    rom_add_blob_fixed("params", params_buf, params_size,
                       (16 << 20) - 264);

    return entry;
}
コード例 #14
0
ファイル: e500.c プロジェクト: evanchueng/qemu
static int ppce500_load_device_tree(CPUPPCState *env,
                                    PPCE500Params *params,
                                    hwaddr addr,
                                    hwaddr initrd_base,
                                    hwaddr initrd_size)
{
    int ret = -1;
    uint64_t mem_reg_property[] = { 0, cpu_to_be64(params->ram_size) };
    int fdt_size;
    void *fdt;
    uint8_t hypercall[16];
    uint32_t clock_freq = 400000000;
    uint32_t tb_freq = 400000000;
    int i;
    const char *toplevel_compat = NULL; /* user override */
    char compatible_sb[] = "fsl,mpc8544-immr\0simple-bus";
    char soc[128];
    char mpic[128];
    uint32_t mpic_ph;
    uint32_t msi_ph;
    char gutil[128];
    char pci[128];
    char msi[128];
    uint32_t *pci_map = NULL;
    int len;
    uint32_t pci_ranges[14] =
        {
            0x2000000, 0x0, 0xc0000000,
            0x0, 0xc0000000,
            0x0, 0x20000000,

            0x1000000, 0x0, 0x0,
            0x0, 0xe1000000,
            0x0, 0x10000,
        };
    QemuOpts *machine_opts;
    const char *dtb_file = NULL;

    machine_opts = qemu_opts_find(qemu_find_opts("machine"), 0);
    if (machine_opts) {
        dtb_file = qemu_opt_get(machine_opts, "dtb");
        toplevel_compat = qemu_opt_get(machine_opts, "dt_compatible");
    }

    if (dtb_file) {
        char *filename;
        filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, dtb_file);
        if (!filename) {
            goto out;
        }

        fdt = load_device_tree(filename, &fdt_size);
        if (!fdt) {
            goto out;
        }
        goto done;
    }

    fdt = create_device_tree(&fdt_size);
    if (fdt == NULL) {
        goto out;
    }

    /* Manipulate device tree in memory. */
    qemu_devtree_setprop_cell(fdt, "/", "#address-cells", 2);
    qemu_devtree_setprop_cell(fdt, "/", "#size-cells", 2);

    qemu_devtree_add_subnode(fdt, "/memory");
    qemu_devtree_setprop_string(fdt, "/memory", "device_type", "memory");
    qemu_devtree_setprop(fdt, "/memory", "reg", mem_reg_property,
                         sizeof(mem_reg_property));

    qemu_devtree_add_subnode(fdt, "/chosen");
    if (initrd_size) {
        ret = qemu_devtree_setprop_cell(fdt, "/chosen", "linux,initrd-start",
                                        initrd_base);
        if (ret < 0) {
            fprintf(stderr, "couldn't set /chosen/linux,initrd-start\n");
        }

        ret = qemu_devtree_setprop_cell(fdt, "/chosen", "linux,initrd-end",
                                        (initrd_base + initrd_size));
        if (ret < 0) {
            fprintf(stderr, "couldn't set /chosen/linux,initrd-end\n");
        }
    }

    ret = qemu_devtree_setprop_string(fdt, "/chosen", "bootargs",
                                      params->kernel_cmdline);
    if (ret < 0)
        fprintf(stderr, "couldn't set /chosen/bootargs\n");

    if (kvm_enabled()) {
        /* Read out host's frequencies */
        clock_freq = kvmppc_get_clockfreq();
        tb_freq = kvmppc_get_tbfreq();

        /* indicate KVM hypercall interface */
        qemu_devtree_add_subnode(fdt, "/hypervisor");
        qemu_devtree_setprop_string(fdt, "/hypervisor", "compatible",
                                    "linux,kvm");
        kvmppc_get_hypercall(env, hypercall, sizeof(hypercall));
        qemu_devtree_setprop(fdt, "/hypervisor", "hcall-instructions",
                             hypercall, sizeof(hypercall));
    }

    /* Create CPU nodes */
    qemu_devtree_add_subnode(fdt, "/cpus");
    qemu_devtree_setprop_cell(fdt, "/cpus", "#address-cells", 1);
    qemu_devtree_setprop_cell(fdt, "/cpus", "#size-cells", 0);

    /* We need to generate the cpu nodes in reverse order, so Linux can pick
       the first node as boot node and be happy */
    for (i = smp_cpus - 1; i >= 0; i--) {
        char cpu_name[128];
        uint64_t cpu_release_addr = MPC8544_SPIN_BASE + (i * 0x20);

        for (env = first_cpu; env != NULL; env = env->next_cpu) {
            if (env->cpu_index == i) {
                break;
            }
        }

        if (!env) {
            continue;
        }

        snprintf(cpu_name, sizeof(cpu_name), "/cpus/PowerPC,8544@%x", env->cpu_index);
        qemu_devtree_add_subnode(fdt, cpu_name);
        qemu_devtree_setprop_cell(fdt, cpu_name, "clock-frequency", clock_freq);
        qemu_devtree_setprop_cell(fdt, cpu_name, "timebase-frequency", tb_freq);
        qemu_devtree_setprop_string(fdt, cpu_name, "device_type", "cpu");
        qemu_devtree_setprop_cell(fdt, cpu_name, "reg", env->cpu_index);
        qemu_devtree_setprop_cell(fdt, cpu_name, "d-cache-line-size",
                                  env->dcache_line_size);
        qemu_devtree_setprop_cell(fdt, cpu_name, "i-cache-line-size",
                                  env->icache_line_size);
        qemu_devtree_setprop_cell(fdt, cpu_name, "d-cache-size", 0x8000);
        qemu_devtree_setprop_cell(fdt, cpu_name, "i-cache-size", 0x8000);
        qemu_devtree_setprop_cell(fdt, cpu_name, "bus-frequency", 0);
        if (env->cpu_index) {
            qemu_devtree_setprop_string(fdt, cpu_name, "status", "disabled");
            qemu_devtree_setprop_string(fdt, cpu_name, "enable-method", "spin-table");
            qemu_devtree_setprop_u64(fdt, cpu_name, "cpu-release-addr",
                                     cpu_release_addr);
        } else {
            qemu_devtree_setprop_string(fdt, cpu_name, "status", "okay");
        }
    }

    qemu_devtree_add_subnode(fdt, "/aliases");
    /* XXX These should go into their respective devices' code */
    snprintf(soc, sizeof(soc), "/soc@%llx", MPC8544_CCSRBAR_BASE);
    qemu_devtree_add_subnode(fdt, soc);
    qemu_devtree_setprop_string(fdt, soc, "device_type", "soc");
    qemu_devtree_setprop(fdt, soc, "compatible", compatible_sb,
                         sizeof(compatible_sb));
    qemu_devtree_setprop_cell(fdt, soc, "#address-cells", 1);
    qemu_devtree_setprop_cell(fdt, soc, "#size-cells", 1);
    qemu_devtree_setprop_cells(fdt, soc, "ranges", 0x0,
                               MPC8544_CCSRBAR_BASE >> 32, MPC8544_CCSRBAR_BASE,
                               MPC8544_CCSRBAR_SIZE);
    /* XXX should contain a reasonable value */
    qemu_devtree_setprop_cell(fdt, soc, "bus-frequency", 0);

    snprintf(mpic, sizeof(mpic), "%s/pic@%llx", soc, MPC8544_MPIC_REGS_OFFSET);
    qemu_devtree_add_subnode(fdt, mpic);
    qemu_devtree_setprop_string(fdt, mpic, "device_type", "open-pic");
    qemu_devtree_setprop_string(fdt, mpic, "compatible", "chrp,open-pic");
    qemu_devtree_setprop_cells(fdt, mpic, "reg", MPC8544_MPIC_REGS_OFFSET,
                               0x40000);
    qemu_devtree_setprop_cell(fdt, mpic, "#address-cells", 0);
    qemu_devtree_setprop_cell(fdt, mpic, "#interrupt-cells", 2);
    mpic_ph = qemu_devtree_alloc_phandle(fdt);
    qemu_devtree_setprop_cell(fdt, mpic, "phandle", mpic_ph);
    qemu_devtree_setprop_cell(fdt, mpic, "linux,phandle", mpic_ph);
    qemu_devtree_setprop(fdt, mpic, "interrupt-controller", NULL, 0);

    /*
     * We have to generate ser1 first, because Linux takes the first
     * device it finds in the dt as serial output device. And we generate
     * devices in reverse order to the dt.
     */
    dt_serial_create(fdt, MPC8544_SERIAL1_REGS_OFFSET,
                     soc, mpic, "serial1", 1, false);
    dt_serial_create(fdt, MPC8544_SERIAL0_REGS_OFFSET,
                     soc, mpic, "serial0", 0, true);

    snprintf(gutil, sizeof(gutil), "%s/global-utilities@%llx", soc,
             MPC8544_UTIL_OFFSET);
    qemu_devtree_add_subnode(fdt, gutil);
    qemu_devtree_setprop_string(fdt, gutil, "compatible", "fsl,mpc8544-guts");
    qemu_devtree_setprop_cells(fdt, gutil, "reg", MPC8544_UTIL_OFFSET, 0x1000);
    qemu_devtree_setprop(fdt, gutil, "fsl,has-rstcr", NULL, 0);

    snprintf(msi, sizeof(msi), "/%s/msi@%llx", soc, MPC8544_MSI_REGS_OFFSET);
    qemu_devtree_add_subnode(fdt, msi);
    qemu_devtree_setprop_string(fdt, msi, "compatible", "fsl,mpic-msi");
    qemu_devtree_setprop_cells(fdt, msi, "reg", MPC8544_MSI_REGS_OFFSET, 0x200);
    msi_ph = qemu_devtree_alloc_phandle(fdt);
    qemu_devtree_setprop_cells(fdt, msi, "msi-available-ranges", 0x0, 0x100);
    qemu_devtree_setprop_phandle(fdt, msi, "interrupt-parent", mpic);
    qemu_devtree_setprop_cells(fdt, msi, "interrupts",
        0xe0, 0x0,
        0xe1, 0x0,
        0xe2, 0x0,
        0xe3, 0x0,
        0xe4, 0x0,
        0xe5, 0x0,
        0xe6, 0x0,
        0xe7, 0x0);
    qemu_devtree_setprop_cell(fdt, msi, "phandle", msi_ph);
    qemu_devtree_setprop_cell(fdt, msi, "linux,phandle", msi_ph);

    snprintf(pci, sizeof(pci), "/pci@%llx", MPC8544_PCI_REGS_BASE);
    qemu_devtree_add_subnode(fdt, pci);
    qemu_devtree_setprop_cell(fdt, pci, "cell-index", 0);
    qemu_devtree_setprop_string(fdt, pci, "compatible", "fsl,mpc8540-pci");
    qemu_devtree_setprop_string(fdt, pci, "device_type", "pci");
    qemu_devtree_setprop_cells(fdt, pci, "interrupt-map-mask", 0xf800, 0x0,
                               0x0, 0x7);
    pci_map = pci_map_create(fdt, qemu_devtree_get_phandle(fdt, mpic),
                             params->pci_first_slot, params->pci_nr_slots,
                             &len);
    qemu_devtree_setprop(fdt, pci, "interrupt-map", pci_map, len);
    qemu_devtree_setprop_phandle(fdt, pci, "interrupt-parent", mpic);
    qemu_devtree_setprop_cells(fdt, pci, "interrupts", 24, 2);
    qemu_devtree_setprop_cells(fdt, pci, "bus-range", 0, 255);
    for (i = 0; i < 14; i++) {
        pci_ranges[i] = cpu_to_be32(pci_ranges[i]);
    }
    qemu_devtree_setprop_cell(fdt, pci, "fsl,msi", msi_ph);
    qemu_devtree_setprop(fdt, pci, "ranges", pci_ranges, sizeof(pci_ranges));
    qemu_devtree_setprop_cells(fdt, pci, "reg", MPC8544_PCI_REGS_BASE >> 32,
                               MPC8544_PCI_REGS_BASE, 0, 0x1000);
    qemu_devtree_setprop_cell(fdt, pci, "clock-frequency", 66666666);
    qemu_devtree_setprop_cell(fdt, pci, "#interrupt-cells", 1);
    qemu_devtree_setprop_cell(fdt, pci, "#size-cells", 2);
    qemu_devtree_setprop_cell(fdt, pci, "#address-cells", 3);
    qemu_devtree_setprop_string(fdt, "/aliases", "pci0", pci);

    params->fixup_devtree(params, fdt);

    if (toplevel_compat) {
        qemu_devtree_setprop(fdt, "/", "compatible", toplevel_compat,
                             strlen(toplevel_compat) + 1);
    }

done:
    qemu_devtree_dumpdtb(fdt, fdt_size);
    ret = rom_add_blob_fixed(BINARY_DEVICE_TREE_FILE, fdt, fdt_size, addr);
    if (ret < 0) {
        goto out;
    }
    g_free(fdt);
    ret = fdt_size;

out:
    g_free(pci_map);

    return ret;
}
コード例 #15
0
static int mpc8544_load_device_tree(target_phys_addr_t addr,
                                     uint32_t ramsize,
                                     target_phys_addr_t initrd_base,
                                     target_phys_addr_t initrd_size,
                                     const char *kernel_cmdline)
{
    int ret = -1;
#ifdef CONFIG_FDT
    uint32_t mem_reg_property[] = {0, ramsize};
    char *filename;
    int fdt_size;
    void *fdt;

    filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, BINARY_DEVICE_TREE_FILE);
    if (!filename) {
        goto out;
    }
    fdt = load_device_tree(filename, &fdt_size);
    qemu_free(filename);
    if (fdt == NULL) {
        goto out;
    }

    /* Manipulate device tree in memory. */
    ret = qemu_devtree_setprop(fdt, "/memory", "reg", mem_reg_property,
                               sizeof(mem_reg_property));
    if (ret < 0)
        fprintf(stderr, "couldn't set /memory/reg\n");

    ret = qemu_devtree_setprop_cell(fdt, "/chosen", "linux,initrd-start",
                                    initrd_base);
    if (ret < 0)
        fprintf(stderr, "couldn't set /chosen/linux,initrd-start\n");

    ret = qemu_devtree_setprop_cell(fdt, "/chosen", "linux,initrd-end",
                                    (initrd_base + initrd_size));
    if (ret < 0)
        fprintf(stderr, "couldn't set /chosen/linux,initrd-end\n");

    ret = qemu_devtree_setprop_string(fdt, "/chosen", "bootargs",
                                      kernel_cmdline);
    if (ret < 0)
        fprintf(stderr, "couldn't set /chosen/bootargs\n");

    if (kvm_enabled()) {
        struct dirent *dirp;
        DIR *dp;
        char buf[128];

        if ((dp = opendir("/proc/device-tree/cpus/")) == NULL) {
            printf("Can't open directory /proc/device-tree/cpus/\n");
            ret = -1;
            goto out;
        }

        buf[0] = '\0';
        while ((dirp = readdir(dp)) != NULL) {
            if (strncmp(dirp->d_name, "PowerPC", 7) == 0) {
                snprintf(buf, 128, "/cpus/%s", dirp->d_name);
                break;
            }
        }
        closedir(dp);
        if (buf[0] == '\0') {
            printf("Unknow host!\n");
            ret = -1;
            goto out;
        }

        mpc8544_copy_soc_cell(fdt, buf, "clock-frequency");
        mpc8544_copy_soc_cell(fdt, buf, "timebase-frequency");
    }

    ret = rom_add_blob_fixed(BINARY_DEVICE_TREE_FILE, fdt, fdt_size, addr);
    qemu_free(fdt);

out:
#endif

    return ret;
}
コード例 #16
0
ファイル: ppc440_bamboo.c プロジェクト: B-Rich/qemu
static int bamboo_load_device_tree(hwaddr addr,
                                     uint32_t ramsize,
                                     hwaddr initrd_base,
                                     hwaddr initrd_size,
                                     const char *kernel_cmdline)
{
    int ret = -1;
    uint32_t mem_reg_property[] = { 0, 0, cpu_to_be32(ramsize) };
    char *filename;
    int fdt_size;
    void *fdt;
    uint32_t tb_freq = 400000000;
    uint32_t clock_freq = 400000000;

    filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, BINARY_DEVICE_TREE_FILE);
    if (!filename) {
        goto out;
    }
    fdt = load_device_tree(filename, &fdt_size);
    g_free(filename);
    if (fdt == NULL) {
        goto out;
    }

    /* Manipulate device tree in memory. */

    ret = qemu_devtree_setprop(fdt, "/memory", "reg", mem_reg_property,
                               sizeof(mem_reg_property));
    if (ret < 0)
        fprintf(stderr, "couldn't set /memory/reg\n");

    ret = qemu_devtree_setprop_cell(fdt, "/chosen", "linux,initrd-start",
                                    initrd_base);
    if (ret < 0)
        fprintf(stderr, "couldn't set /chosen/linux,initrd-start\n");

    ret = qemu_devtree_setprop_cell(fdt, "/chosen", "linux,initrd-end",
                                    (initrd_base + initrd_size));
    if (ret < 0)
        fprintf(stderr, "couldn't set /chosen/linux,initrd-end\n");

    ret = qemu_devtree_setprop_string(fdt, "/chosen", "bootargs",
                                      kernel_cmdline);
    if (ret < 0)
        fprintf(stderr, "couldn't set /chosen/bootargs\n");

    /* Copy data from the host device tree into the guest. Since the guest can
     * directly access the timebase without host involvement, we must expose
     * the correct frequencies. */
    if (kvm_enabled()) {
        tb_freq = kvmppc_get_tbfreq();
        clock_freq = kvmppc_get_clockfreq();
    }

    qemu_devtree_setprop_cell(fdt, "/cpus/cpu@0", "clock-frequency",
                              clock_freq);
    qemu_devtree_setprop_cell(fdt, "/cpus/cpu@0", "timebase-frequency",
                              tb_freq);

    rom_add_blob_fixed(BINARY_DEVICE_TREE_FILE, fdt, fdt_size, addr);
    g_free(fdt);
    return 0;

out:

    return ret;
}
コード例 #17
0
ファイル: r2d.c プロジェクト: EgoIncarnate/qemu-rr
static void r2d_init(ram_addr_t ram_size,
              const char *boot_device,
	      const char *kernel_filename, const char *kernel_cmdline,
	      const char *initrd_filename, const char *cpu_model)
{
    CPUState *env;
    struct SH7750State *s;
    ram_addr_t sdram_addr;
    qemu_irq *irq;
    DriveInfo *dinfo;
    int i;

    if (!cpu_model)
        cpu_model = "SH7751R";

    env = cpu_init(cpu_model);
    if (!env) {
        fprintf(stderr, "Unable to find CPU definition\n");
        exit(1);
    }

    /* Allocate memory space */
    sdram_addr = qemu_ram_alloc(NULL, "r2d.sdram", SDRAM_SIZE);
    cpu_register_physical_memory(SDRAM_BASE, SDRAM_SIZE, sdram_addr);
    /* Register peripherals */
    s = sh7750_init(env);
    irq = r2d_fpga_init(0x04000000, sh7750_irl(s));
    sh_pci_register_bus(r2d_pci_set_irq, r2d_pci_map_irq, irq, 0, 4);

    sm501_init(0x10000000, SM501_VRAM_SIZE, irq[SM501], serial_hds[2]);

    /* onboard CF (True IDE mode, Master only). */
    dinfo = drive_get(IF_IDE, 0, 0);
    mmio_ide_init(0x14001000, 0x1400080c, irq[CF_IDE], 1,
                  dinfo, NULL);

    /* onboard flash memory */
    dinfo = drive_get(IF_PFLASH, 0, 0);
    pflash_cfi02_register(0x0, qemu_ram_alloc(NULL, "r2d.flash", FLASH_SIZE),
                          dinfo ? dinfo->bdrv : NULL, (16 * 1024),
                          FLASH_SIZE >> 16,
                          1, 4, 0x0000, 0x0000, 0x0000, 0x0000,
                          0x555, 0x2aa, 0);

    /* NIC: rtl8139 on-board, and 2 slots. */
    for (i = 0; i < nb_nics; i++)
        pci_nic_init_nofail(&nd_table[i], "rtl8139", i==0 ? "2" : NULL);

    /* USB keyboard */
    usbdevice_create("keyboard");

    /* Todo: register on board registers */
    memset(&boot_params, 0, sizeof(boot_params));

    if (kernel_filename) {
        int kernel_size;

        kernel_size = load_image_targphys(kernel_filename,
                                          SDRAM_BASE + LINUX_LOAD_OFFSET,
                                          INITRD_LOAD_OFFSET - LINUX_LOAD_OFFSET);
        if (kernel_size < 0) {
          fprintf(stderr, "qemu: could not load kernel '%s'\n", kernel_filename);
          exit(1);
        }

        /* initialization which should be done by firmware */
        stl_phys(SH7750_BCR1, 1<<3); /* cs3 SDRAM */
        stw_phys(SH7750_BCR2, 3<<(3*2)); /* cs3 32bit */
        env->pc = (SDRAM_BASE + LINUX_LOAD_OFFSET) | 0xa0000000; /* Start from P2 area */
    }

    if (initrd_filename) {
        int initrd_size;

        initrd_size = load_image_targphys(initrd_filename,
                                          SDRAM_BASE + INITRD_LOAD_OFFSET,
                                          SDRAM_SIZE - INITRD_LOAD_OFFSET);

        if (initrd_size < 0) {
          fprintf(stderr, "qemu: could not load initrd '%s'\n", initrd_filename);
          exit(1);
        }

        /* initialization which should be done by firmware */
        boot_params.loader_type = 1;
        boot_params.initrd_start = INITRD_LOAD_OFFSET;
        boot_params.initrd_size = initrd_size;
    }

    if (kernel_cmdline) {
        strncpy(boot_params.kernel_cmdline, kernel_cmdline,
                sizeof(boot_params.kernel_cmdline));
    }

    rom_add_blob_fixed("boot_params", &boot_params, sizeof(boot_params),
                       SDRAM_BASE + BOOT_PARAMS_OFFSET);
}