Ejemplo n.º 1
0
int fdt_create_empty_tree(void *buf, int bufsize)
{
	int err;

	err = fdt_create(buf, bufsize);
	if (err)
		return err;

	err = fdt_finish_reservemap(buf);
	if (err)
		return err;

	err = fdt_begin_node(buf, "");
	if (err)
		return err;

	err =  fdt_end_node(buf);
	if (err)
		return err;

	err = fdt_finish(buf);
	if (err)
		return err;

	return fdt_open_into(buf, buf, bufsize);
}
Ejemplo n.º 2
0
void *create_device_tree(int *sizep)
{
    void *fdt;
    int ret;

    *sizep = FDT_MAX_SIZE;
    fdt = g_malloc0(FDT_MAX_SIZE);
    ret = fdt_create(fdt, FDT_MAX_SIZE);
    if (ret < 0) {
        goto fail;
    }
    ret = fdt_begin_node(fdt, "");
    if (ret < 0) {
        goto fail;
    }
    ret = fdt_end_node(fdt);
    if (ret < 0) {
        goto fail;
    }
    ret = fdt_finish(fdt);
    if (ret < 0) {
        goto fail;
    }
    ret = fdt_open_into(fdt, fdt, *sizep);
    if (ret) {
        fprintf(stderr, "Unable to copy device tree in memory\n");
        exit(1);
    }

    return fdt;
fail:
    fprintf(stderr, "%s Couldn't create dt: %s\n", __func__, fdt_strerror(ret));
    exit(1);
}
Ejemplo n.º 3
0
int main(int argc, char *argv[])
{
	void *fdt;
	int err;
	int offset, s1, s2;

	test_init(argc, argv);

	fdt = xmalloc(SPACE);

	/* First create empty tree with SW */
	CHECK(fdt_create(fdt, SPACE));

	CHECK(fdt_finish_reservemap(fdt));
	CHECK(fdt_begin_node(fdt, ""));
	CHECK(fdt_end_node(fdt));
	CHECK(fdt_finish(fdt));

	verbose_printf("Built empty tree, totalsize = %d\n",
		       fdt_totalsize(fdt));

	CHECK(fdt_open_into(fdt, fdt, SPACE));

	CHECK(fdt_add_mem_rsv(fdt, TEST_ADDR_1, TEST_SIZE_1));
	CHECK(fdt_add_mem_rsv(fdt, TEST_ADDR_2, TEST_SIZE_2));

	CHECK(fdt_setprop_string(fdt, 0, "compatible", "test_tree1"));
	CHECK(fdt_setprop_cell(fdt, 0, "prop-int", TEST_VALUE_1));
	CHECK(fdt_setprop_string(fdt, 0, "prop-str", TEST_STRING_1));

	OFF_CHECK(offset, fdt_add_subnode(fdt, 0, "subnode@1"));
	s1 = offset;
	CHECK(fdt_setprop_string(fdt, s1, "compatible", "subnode1"));
	CHECK(fdt_setprop_cell(fdt, s1, "prop-int", TEST_VALUE_1));
	OFF_CHECK(offset, fdt_add_subnode(fdt, s1, "subsubnode"));
	CHECK(fdt_setprop(fdt, offset, "compatible",
			  "subsubnode1\0subsubnode", 23));
	CHECK(fdt_setprop_cell(fdt, offset, "prop-int", TEST_VALUE_1));
	OFF_CHECK(offset, fdt_add_subnode(fdt, s1, "ss1"));

	OFF_CHECK(offset, fdt_add_subnode(fdt, 0, "subnode@2"));
	s2 = offset;
	CHECK(fdt_setprop_cell(fdt, s2, "linux,phandle", PHANDLE_1));
	CHECK(fdt_setprop_cell(fdt, s2, "prop-int", TEST_VALUE_2));
	OFF_CHECK(offset, fdt_add_subnode(fdt, s2, "subsubnode@0"));
	CHECK(fdt_setprop_cell(fdt, offset, "linux,phandle", PHANDLE_2));
	CHECK(fdt_setprop(fdt, offset, "compatible",
			  "subsubnode2\0subsubnode", 23));
	CHECK(fdt_setprop_cell(fdt, offset, "prop-int", TEST_VALUE_2));
	OFF_CHECK(offset, fdt_add_subnode(fdt, s2, "ss2"));

	CHECK(fdt_pack(fdt));

	save_blob("rw_tree1.test.dtb", fdt);

	PASS();
}
Ejemplo n.º 4
0
/*
 * Make a test fdt
 *
 * @param fdt		Device tree pointer
 * @param size		Size of device tree blob
 * @param aliases	Specifies alias assignments. Format is a list of items
 *			separated by space. Items are #a where
 *				# is the alias number
 *				a is the node to point to
 * @param nodes		Specifies nodes to generate (a=0, b=1), upper case
 *			means to create a disabled node
 */
static int make_fdt(void *fdt, int size, const char *aliases,
		    const char *nodes)
{
	char name[20], value[20];
	const char *s;
	int fd;

	CHECK(fdt_create(fdt, size));
	CHECK(fdt_finish_reservemap(fdt));
	CHECK(fdt_begin_node(fdt, ""));

	CHECK(fdt_begin_node(fdt, "aliases"));
	for (s = aliases; *s;) {
		sprintf(name, "i2c%c", *s);
		sprintf(value, "/i2c%d@0", s[1] - 'a');
		CHECK(fdt_property_string(fdt, name, value));
		s += 2 + (s[2] != '\0');
	}
	CHECK(fdt_end_node(fdt));

	for (s = nodes; *s; s++) {
		sprintf(value, "i2c%d@0", (*s & 0xdf) - 'A');
		CHECK(fdt_begin_node(fdt, value));
		CHECK(fdt_property_string(fdt, "compatible",
			fdtdec_get_compatible(COMPAT_UNKNOWN)));
		if (*s <= 'Z')
			CHECK(fdt_property_string(fdt, "status", "disabled"));
		CHECK(fdt_end_node(fdt));
	}

	CHECK(fdt_end_node(fdt));
	CHECK(fdt_finish(fdt));
	CHECK(fdt_pack(fdt));
#if defined(DEBUG) && defined(CONFIG_SANDBOX)
	fd = os_open("/tmp/fdtdec-text.dtb", OS_O_CREAT | OS_O_WRONLY);
	if (fd == -1) {
		printf("Could not open .dtb file to write\n");
		return -1;
	}
	os_write(fd, fdt, size);
	os_close(fd);
#endif
	return 0;
}
Ejemplo n.º 5
0
static void *spapr_create_fdt_skel(const char *cpu_model,
                                   target_phys_addr_t initrd_base,
                                   target_phys_addr_t initrd_size,
                                   const char *boot_device,
                                   const char *kernel_cmdline,
                                   long hash_shift)
{
    void *fdt;
    CPUState *env;
    uint64_t mem_reg_property[] = { 0, cpu_to_be64(ram_size) };
    uint32_t start_prop = cpu_to_be32(initrd_base);
    uint32_t end_prop = cpu_to_be32(initrd_base + initrd_size);
    uint32_t pft_size_prop[] = {0, cpu_to_be32(hash_shift)};
    char hypertas_prop[] = "hcall-pft\0hcall-term\0hcall-dabr\0hcall-interrupt"
        "\0hcall-tce\0hcall-vio\0hcall-splpar";
    uint32_t interrupt_server_ranges_prop[] = {0, cpu_to_be32(smp_cpus)};
    int i;
    char *modelname;

#define _FDT(exp) \
    do { \
        int ret = (exp);                                           \
        if (ret < 0) {                                             \
            fprintf(stderr, "qemu: error creating device tree: %s: %s\n", \
                    #exp, fdt_strerror(ret));                      \
            exit(1);                                               \
        }                                                          \
    } while (0)

    fdt = qemu_mallocz(FDT_MAX_SIZE);
    _FDT((fdt_create(fdt, FDT_MAX_SIZE)));

    _FDT((fdt_finish_reservemap(fdt)));

    /* Root node */
    _FDT((fdt_begin_node(fdt, "")));
    _FDT((fdt_property_string(fdt, "device_type", "chrp")));
    _FDT((fdt_property_string(fdt, "model", "qemu,emulated-pSeries-LPAR")));

    _FDT((fdt_property_cell(fdt, "#address-cells", 0x2)));
    _FDT((fdt_property_cell(fdt, "#size-cells", 0x2)));

    /* /chosen */
    _FDT((fdt_begin_node(fdt, "chosen")));

    _FDT((fdt_property_string(fdt, "bootargs", kernel_cmdline)));
    _FDT((fdt_property(fdt, "linux,initrd-start",
                       &start_prop, sizeof(start_prop))));
    _FDT((fdt_property(fdt, "linux,initrd-end",
                       &end_prop, sizeof(end_prop))));
    _FDT((fdt_property_string(fdt, "qemu,boot-device", boot_device)));

    _FDT((fdt_end_node(fdt)));

    /* memory node */
    _FDT((fdt_begin_node(fdt, "memory@0")));

    _FDT((fdt_property_string(fdt, "device_type", "memory")));
    _FDT((fdt_property(fdt, "reg",
                       mem_reg_property, sizeof(mem_reg_property))));

    _FDT((fdt_end_node(fdt)));

    /* cpus */
    _FDT((fdt_begin_node(fdt, "cpus")));

    _FDT((fdt_property_cell(fdt, "#address-cells", 0x1)));
    _FDT((fdt_property_cell(fdt, "#size-cells", 0x0)));

    modelname = qemu_strdup(cpu_model);

    for (i = 0; i < strlen(modelname); i++) {
        modelname[i] = toupper(modelname[i]);
    }

    for (env = first_cpu; env != NULL; env = env->next_cpu) {
        int index = env->cpu_index;
        uint32_t gserver_prop[] = {cpu_to_be32(index), 0}; /* HACK! */
        char *nodename;
        uint32_t segs[] = {cpu_to_be32(28), cpu_to_be32(40),
                           0xffffffff, 0xffffffff};

        if (asprintf(&nodename, "%s@%x", modelname, index) < 0) {
            fprintf(stderr, "Allocation failure\n");
            exit(1);
        }

        _FDT((fdt_begin_node(fdt, nodename)));

        free(nodename);

        _FDT((fdt_property_cell(fdt, "reg", index)));
        _FDT((fdt_property_string(fdt, "device_type", "cpu")));

        _FDT((fdt_property_cell(fdt, "cpu-version", env->spr[SPR_PVR])));
        _FDT((fdt_property_cell(fdt, "dcache-block-size",
                                env->dcache_line_size)));
        _FDT((fdt_property_cell(fdt, "icache-block-size",
                                env->icache_line_size)));
        _FDT((fdt_property_cell(fdt, "timebase-frequency", TIMEBASE_FREQ)));
        /* Hardcode CPU frequency for now.  It's kind of arbitrary on
         * full emu, for kvm we should copy it from the host */
        _FDT((fdt_property_cell(fdt, "clock-frequency", 1000000000)));
        _FDT((fdt_property_cell(fdt, "ibm,slb-size", env->slb_nr)));
        _FDT((fdt_property(fdt, "ibm,pft-size",
                           pft_size_prop, sizeof(pft_size_prop))));
        _FDT((fdt_property_string(fdt, "status", "okay")));
        _FDT((fdt_property(fdt, "64-bit", NULL, 0)));
        _FDT((fdt_property_cell(fdt, "ibm,ppc-interrupt-server#s", index)));
        _FDT((fdt_property(fdt, "ibm,ppc-interrupt-gserver#s",
                           gserver_prop, sizeof(gserver_prop))));

        if (env->mmu_model & POWERPC_MMU_1TSEG) {
            _FDT((fdt_property(fdt, "ibm,processor-segment-sizes",
                               segs, sizeof(segs))));
        }

        _FDT((fdt_end_node(fdt)));
    }

    qemu_free(modelname);

    _FDT((fdt_end_node(fdt)));

    /* RTAS */
    _FDT((fdt_begin_node(fdt, "rtas")));

    _FDT((fdt_property(fdt, "ibm,hypertas-functions", hypertas_prop,
                       sizeof(hypertas_prop))));

    _FDT((fdt_end_node(fdt)));

    /* interrupt controller */
    _FDT((fdt_begin_node(fdt, "interrupt-controller@0")));

    _FDT((fdt_property_string(fdt, "device_type",
                              "PowerPC-External-Interrupt-Presentation")));
    _FDT((fdt_property_string(fdt, "compatible", "IBM,ppc-xicp")));
    _FDT((fdt_property_cell(fdt, "reg", 0)));
    _FDT((fdt_property(fdt, "interrupt-controller", NULL, 0)));
    _FDT((fdt_property(fdt, "ibm,interrupt-server-ranges",
                       interrupt_server_ranges_prop,
                       sizeof(interrupt_server_ranges_prop))));

    _FDT((fdt_end_node(fdt)));

    /* vdevice */
    _FDT((fdt_begin_node(fdt, "vdevice")));

    _FDT((fdt_property_string(fdt, "device_type", "vdevice")));
    _FDT((fdt_property_string(fdt, "compatible", "IBM,vdevice")));
    _FDT((fdt_property_cell(fdt, "#address-cells", 0x1)));
    _FDT((fdt_property_cell(fdt, "#size-cells", 0x0)));
    _FDT((fdt_property_cell(fdt, "#interrupt-cells", 0x2)));
    _FDT((fdt_property(fdt, "interrupt-controller", NULL, 0)));

    _FDT((fdt_end_node(fdt)));

    _FDT((fdt_end_node(fdt))); /* close root node */
    _FDT((fdt_finish(fdt)));

    return fdt;
}
Ejemplo n.º 6
0
static int setup_fdt(struct kvm *kvm)
{
	struct device_header *dev_hdr;
	u8 staging_fdt[FDT_MAX_SIZE];
	u32 gic_phandle		= fdt__alloc_phandle();
	u64 mem_reg_prop[]	= {
		cpu_to_fdt64(kvm->arch.memory_guest_start),
		cpu_to_fdt64(kvm->ram_size),
	};
	void *fdt		= staging_fdt;
	void *fdt_dest		= guest_flat_to_host(kvm,
						     kvm->arch.dtb_guest_start);
	void (*generate_mmio_fdt_nodes)(void *, struct device_header *,
					void (*)(void *, u8));
	void (*generate_cpu_peripheral_fdt_nodes)(void *, struct kvm *, u32)
					= kvm->cpus[0]->generate_fdt_nodes;

	/* Create new tree without a reserve map */
	_FDT(fdt_create(fdt, FDT_MAX_SIZE));
	_FDT(fdt_finish_reservemap(fdt));

	/* Header */
	_FDT(fdt_begin_node(fdt, ""));
	_FDT(fdt_property_cell(fdt, "interrupt-parent", gic_phandle));
	_FDT(fdt_property_string(fdt, "compatible", "linux,dummy-virt"));
	_FDT(fdt_property_cell(fdt, "#address-cells", 0x2));
	_FDT(fdt_property_cell(fdt, "#size-cells", 0x2));

	/* /chosen */
	_FDT(fdt_begin_node(fdt, "chosen"));
	_FDT(fdt_property_cell(fdt, "linux,pci-probe-only", 1));
	_FDT(fdt_property_string(fdt, "bootargs", kern_cmdline));

	/* Initrd */
	if (kvm->arch.initrd_size != 0) {
		u32 ird_st_prop = cpu_to_fdt64(kvm->arch.initrd_guest_start);
		u32 ird_end_prop = cpu_to_fdt64(kvm->arch.initrd_guest_start +
					       kvm->arch.initrd_size);

		_FDT(fdt_property(fdt, "linux,initrd-start",
				   &ird_st_prop, sizeof(ird_st_prop)));
		_FDT(fdt_property(fdt, "linux,initrd-end",
				   &ird_end_prop, sizeof(ird_end_prop)));
	}
	_FDT(fdt_end_node(fdt));

	/* Memory */
	_FDT(fdt_begin_node(fdt, "memory"));
	_FDT(fdt_property_string(fdt, "device_type", "memory"));
	_FDT(fdt_property(fdt, "reg", mem_reg_prop, sizeof(mem_reg_prop)));
	_FDT(fdt_end_node(fdt));

	/* CPU and peripherals (interrupt controller, timers, etc) */
	generate_cpu_nodes(fdt, kvm);
	if (generate_cpu_peripheral_fdt_nodes)
		generate_cpu_peripheral_fdt_nodes(fdt, kvm, gic_phandle);

	/* Virtio MMIO devices */
	dev_hdr = device__first_dev(DEVICE_BUS_MMIO);
	while (dev_hdr) {
		generate_mmio_fdt_nodes = dev_hdr->data;
		generate_mmio_fdt_nodes(fdt, dev_hdr, generate_irq_prop);
		dev_hdr = device__next_dev(dev_hdr);
	}

	/* IOPORT devices (!) */
	dev_hdr = device__first_dev(DEVICE_BUS_IOPORT);
	while (dev_hdr) {
		generate_mmio_fdt_nodes = dev_hdr->data;
		generate_mmio_fdt_nodes(fdt, dev_hdr, generate_irq_prop);
		dev_hdr = device__next_dev(dev_hdr);
	}

	/* PCI host controller */
	pci__generate_fdt_nodes(fdt, gic_phandle);

	/* PSCI firmware */
	_FDT(fdt_begin_node(fdt, "psci"));
	_FDT(fdt_property_string(fdt, "compatible", "arm,psci"));
	_FDT(fdt_property_string(fdt, "method", "hvc"));
	_FDT(fdt_property_cell(fdt, "cpu_suspend", KVM_PSCI_FN_CPU_SUSPEND));
	_FDT(fdt_property_cell(fdt, "cpu_off", KVM_PSCI_FN_CPU_OFF));
	_FDT(fdt_property_cell(fdt, "cpu_on", KVM_PSCI_FN_CPU_ON));
	_FDT(fdt_property_cell(fdt, "migrate", KVM_PSCI_FN_MIGRATE));
	_FDT(fdt_end_node(fdt));

	/* Finalise. */
	_FDT(fdt_end_node(fdt));
	_FDT(fdt_finish(fdt));

	_FDT(fdt_open_into(fdt, fdt_dest, FDT_MAX_SIZE));
	_FDT(fdt_pack(fdt_dest));

	if (kvm->cfg.arch.dump_dtb_filename)
		dump_fdt(kvm->cfg.arch.dump_dtb_filename, fdt_dest);
	return 0;
}
Ejemplo n.º 7
0
/*
 * Load program and start running it in usermode
 * in a new thread.
 * This is essentially an amalgam of fork() and execv().
 */
int
runprogram(int nargs, char **args, struct process **created_proc)
{
    if (nargs > ARGNUM_MAX)
        return E2BIG;
    
	struct vnode *v;
	int result;
    struct process *proc;
    
    // copy the string, since vfs_open() will modify it
    char *progname = kstrdup(args[0]);
    if (progname == NULL)
        return ENOMEM;

	/* Open the file. */
	result = vfs_open(progname, O_RDONLY, 0, &v);
	if (result) {
		return result;
	}
    
    // We no longer need the duplicate program name
    kfree(progname);

    // set up new process structure
    proc = process_create(args[0]);
    if (proc == NULL)
    {
        vfs_close(v);
        return ENOMEM;
    }
    
    // Get a PID for the process.  ENPROC is
    // the error code for "no more processes allowed
    // in the system."
    pid_t pid = process_identify(proc);
    if (pid == 0)
    {
        process_cleanup(proc);
        vfs_close(v);
        return ENPROC;
    }
    
    // Create a new file descriptor table
    proc->ps_fdt = fdt_create();
    if (proc->ps_fdt == NULL)
    {
        process_destroy(pid);
        vfs_close(v);
        return ENOMEM;
    }
    
    // Open FDs for stdin, stdout, and stderr
    result = setup_inouterr(proc->ps_fdt);
    if (result)
    {
        process_destroy(pid);
        vfs_close(v);
        return result;
    }
    
	// Create a new address space
	proc->ps_addrspace = as_create();
	if (proc->ps_addrspace==NULL) {
        process_destroy(pid);
		vfs_close(v);
		return ENOMEM;
	}
    
    struct new_process_context *ctxt = kmalloc(sizeof(struct new_process_context));
    if (ctxt == NULL)
    {
        as_activate(NULL);
        process_destroy(pid);
        return ENOMEM;
    }
    ctxt->nargs = nargs;
    ctxt->args = args;
    ctxt->proc = proc;
    ctxt->executable = v;

	// Start a new thread to warp to user mode
    result = thread_fork("user process",
                         run_process,
                         ctxt, 0, NULL);
    if (result)
    {
        kfree(ctxt);
        as_activate(NULL);
        process_destroy(pid);
        return result;
    }
    
    // pass process to caller and return
    *created_proc = proc;
	return 0;
}
Ejemplo n.º 8
0
/**
 * build_tree() - Build a tree
 *
 * @fdt:	Pointer to place to put tree, assumed to be large enough
 * @flags:	Flags to control the tree creation (FDT_REG_...)
 * @space:	Amount of space to create for later tree additions
 *
 * This creates a tree modelled on a U-Boot FIT image, with various nodes
 * and properties which are useful for testing the hashing features of
 * fdt_find_regions().
 *
 * See h_include() below for a list of the nodes we later search for.
 */
static void build_tree(void *fdt, int flags, int space)
{
	int direct_subnodes = flags & FDT_REG_DIRECT_SUBNODES;
	int all_subnodes = flags & FDT_REG_ALL_SUBNODES;
	int supernodes = flags & FDT_REG_SUPERNODES;
	int either = !all_subnodes && (direct_subnodes || supernodes);
	int err;

	CHECK(fdt_create(fdt, SPACE));

	CHECK(fdt_add_reservemap_entry(fdt, TEST_ADDR_1, TEST_SIZE_1));
	CHECK(fdt_add_reservemap_entry(fdt, TEST_ADDR_2, TEST_SIZE_2));
	CHECK(fdt_finish_reservemap(fdt));

	/*
	 * This is the start of a new region because in the fdt_xxx_region()
	 * call, we pass "/" as one of the nodes to find.
	 */
	start(fdt);	/* region 0 */
	CHECK(fdt_begin_node(fdt, ""));
	CHECK(fdt_property_string(fdt, "description", "kernel image"));
	CHECK(fdt_property_u32(fdt, "#address-cells", 1));

	/* /images */
	if (!either && !all_subnodes)
		stop(fdt);
	CHECK(fdt_begin_node(fdt, "images"));
	if (either)
		stop(fdt);
	CHECK(fdt_property_u32(fdt, "image-prop", 1));

	/* /images/kernel@1 */
	if (!all_subnodes)
		start(fdt);	/* region 1 */
	CHECK(fdt_begin_node(fdt, "kernel@1"));
	CHECK(fdt_property_string(fdt, "description", "exynos kernel"));
	stop(fdt);
	CHECK(fdt_property_string(fdt, "data", "this is the kernel image"));
	start(fdt);	/* region 2 */

	/* /images/kernel/hash@1 */
	CHECK(fdt_begin_node(fdt, "hash@1"));
	CHECK(fdt_property_string(fdt, "algo", "sha1"));
	CHECK(fdt_end_node(fdt));

	/* /images/kernel/hash@2 */
	if (!direct_subnodes)
		stop(fdt);
	CHECK(fdt_begin_node(fdt, "hash@2"));
	if (direct_subnodes)
		stop(fdt);
	CHECK(fdt_property_string(fdt, "algo", "sha1"));
	if (direct_subnodes)
		start(fdt);	/* region 3 */
	CHECK(fdt_end_node(fdt));
	if (!direct_subnodes)
		start(fdt);	/* region 3 */

	CHECK(fdt_end_node(fdt));

	/* /images/fdt@1 */
	CHECK(fdt_begin_node(fdt, "fdt@1"));
	CHECK(fdt_property_string(fdt, "description", "snow FDT"));
	if (!all_subnodes)
		stop(fdt);
	CHECK(fdt_property_string(fdt, "data", "FDT data"));
	if (!all_subnodes)
		start(fdt);	/* region 4 */

	/* /images/kernel/hash@1 */
	CHECK(fdt_begin_node(fdt, "hash@1"));
	CHECK(fdt_property_string(fdt, "algo", "sha1"));
	CHECK(fdt_end_node(fdt));

	CHECK(fdt_end_node(fdt));

	if (!either && !all_subnodes)
		stop(fdt);
	CHECK(fdt_end_node(fdt));

	/* /configurations */
	CHECK(fdt_begin_node(fdt, "configurations"));
	if (either)
		stop(fdt);
	CHECK(fdt_property_string(fdt, "default", "conf@1"));

	/* /configurations/conf@1 */
	if (!all_subnodes)
		start(fdt);	/* region 6 */
	CHECK(fdt_begin_node(fdt, "conf@1"));
	CHECK(fdt_property_string(fdt, "kernel", "kernel@1"));
	CHECK(fdt_property_string(fdt, "fdt", "fdt@1"));
	CHECK(fdt_end_node(fdt));
	if (!all_subnodes)
		stop(fdt);

	/* /configurations/conf@2 */
	CHECK(fdt_begin_node(fdt, "conf@2"));
	CHECK(fdt_property_string(fdt, "kernel", "kernel@1"));
	CHECK(fdt_property_string(fdt, "fdt", "fdt@2"));
	CHECK(fdt_end_node(fdt));

	if (either)
		start(fdt);	/* region 7 */
	CHECK(fdt_end_node(fdt));
	if (!either && !all_subnodes)
		start(fdt);	/* region 7 */

	CHECK(fdt_end_node(fdt));

	CHECK(fdt_finish(fdt));
	stop(fdt);

	/* Add in the strings */
	if (flags & FDT_REG_ADD_STRING_TAB) {
		expect[expect_count].offset = fdt_off_dt_strings(fdt);
		expect[expect_count].size = fdt_size_dt_strings(fdt);
		expect_count++;
	}

	/* Make a bit of space */
	if (space)
		CHECK(fdt_open_into(fdt, fdt, fdt_totalsize(fdt) + space));

	verbose_printf("Completed tree, totalsize = %d\n", fdt_totalsize(fdt));
}
Ejemplo n.º 9
0
static void versal_virt_init(MachineState *machine)
{
    VersalVirt *s = XLNX_VERSAL_VIRT_MACHINE(machine);
    int psci_conduit = QEMU_PSCI_CONDUIT_DISABLED;

    /*
     * If the user provides an Operating System to be loaded, we expect them
     * to use the -kernel command line option.
     *
     * Users can load firmware or boot-loaders with the -device loader options.
     *
     * When loading an OS, we generate a dtb and let arm_load_kernel() select
     * where it gets loaded. This dtb will be passed to the kernel in x0.
     *
     * If there's no -kernel option, we generate a DTB and place it at 0x1000
     * for the bootloaders or firmware to pick up.
     *
     * If users want to provide their own DTB, they can use the -dtb option.
     * These dtb's will have their memory nodes modified to match QEMU's
     * selected ram_size option before they get passed to the kernel or fw.
     *
     * When loading an OS, we turn on QEMU's PSCI implementation with SMC
     * as the PSCI conduit. When there's no -kernel, we assume the user
     * provides EL3 firmware to handle PSCI.
     */
    if (machine->kernel_filename) {
        psci_conduit = QEMU_PSCI_CONDUIT_SMC;
    }

    memory_region_allocate_system_memory(&s->mr_ddr, NULL, "ddr",
                                         machine->ram_size);

    sysbus_init_child_obj(OBJECT(machine), "xlnx-ve", &s->soc,
                          sizeof(s->soc), TYPE_XLNX_VERSAL);
    object_property_set_link(OBJECT(&s->soc), OBJECT(&s->mr_ddr),
                             "ddr", &error_abort);
    object_property_set_int(OBJECT(&s->soc), psci_conduit,
                            "psci-conduit", &error_abort);
    object_property_set_bool(OBJECT(&s->soc), true, "realized", &error_fatal);

    fdt_create(s);
    create_virtio_regions(s);
    fdt_add_gem_nodes(s);
    fdt_add_uart_nodes(s);
    fdt_add_gic_nodes(s);
    fdt_add_timer_nodes(s);
    fdt_add_cpu_nodes(s, psci_conduit);
    fdt_add_clk_node(s, "/clk125", 125000000, s->phandle.clk_125Mhz);
    fdt_add_clk_node(s, "/clk25", 25000000, s->phandle.clk_25Mhz);

    /* Make the APU cpu address space visible to virtio and other
     * modules unaware of muliple address-spaces.  */
    memory_region_add_subregion_overlap(get_system_memory(),
                                        0, &s->soc.fpd.apu.mr, 0);

    s->binfo.ram_size = machine->ram_size;
    s->binfo.kernel_filename = machine->kernel_filename;
    s->binfo.kernel_cmdline = machine->kernel_cmdline;
    s->binfo.initrd_filename = machine->initrd_filename;
    s->binfo.loader_start = 0x0;
    s->binfo.get_dtb = versal_virt_get_dtb;
    s->binfo.modify_dtb = versal_virt_modify_dtb;
    if (machine->kernel_filename) {
        arm_load_kernel(s->soc.fpd.apu.cpu[0], &s->binfo);
    } else {
        AddressSpace *as = arm_boot_address_space(s->soc.fpd.apu.cpu[0],
                                                  &s->binfo);
        /* Some boot-loaders (e.g u-boot) don't like blobs at address 0 (NULL).
         * Offset things by 4K.  */
        s->binfo.loader_start = 0x1000;
        s->binfo.dtb_limit = 0x1000000;
        if (arm_load_dtb(s->binfo.loader_start,
                         &s->binfo, s->binfo.dtb_limit, as) < 0) {
            exit(EXIT_FAILURE);
        }
    }
}