static int __init process_acpi_sdt_table(char *tab_sign, u32 *tab_data)
{
    struct vmm_devtree_node *node = vmm_devtree_getnode(VMM_DEVTREE_PATH_SEPARATOR_STRING
                                    VMM_DEVTREE_MOTHERBOARD_NODE_NAME);
    /* FIXME: First find if tab_size already exists. */
    struct vmm_devtree_node *cnode = vmm_devtree_addnode(node, tab_sign);

    vmm_devtree_dref_node(node);
    if (!strncmp(tab_sign, APIC_SIGNATURE, strlen(APIC_SIGNATURE))) {
        struct acpi_madt_hdr *madt_hdr;
        madt_hdr = (struct acpi_madt_hdr *)tab_data;
        if (acpi_populate_ioapic_devtree(madt_hdr, cnode) != VMM_OK)
            return VMM_EFAIL;

        if (acpi_populate_lapic_devtree(madt_hdr, cnode) != VMM_OK)
            return VMM_EFAIL;
    } else if (!strncmp(tab_sign, HPET_SIGNATURE, strlen(HPET_SIGNATURE))) {
        struct acpi_hpet hpet_chip, *hpet;
        int nr_hpet_blks, i;
        char hpet_nm[256];

        if (acpi_read_sdt_at(tab_data,
                             (struct acpi_sdt_hdr *)&hpet_chip,
                             sizeof(struct acpi_hpet),
                             HPET_SIGNATURE) < 0) {
            return VMM_EFAIL;
        }

        hpet = (struct acpi_hpet *)tab_data;
        nr_hpet_blks = (hpet->hdr.len - sizeof(struct acpi_sdt_hdr))
                       /sizeof(struct acpi_timer_blocks);

        vmm_devtree_setattr(cnode, VMM_DEVTREE_NR_HPET_ATTR_NAME,
                            &nr_hpet_blks, VMM_DEVTREE_ATTRTYPE_UINT32,
                            sizeof(nr_hpet_blks), FALSE);

        for (i = 0; i < nr_hpet_blks; i++) {
            memset(hpet_nm, 0, sizeof(hpet_nm));
            vmm_sprintf(hpet_nm, VMM_DEVTREE_HPET_NODE_FMT, i);
            struct vmm_devtree_node *nnode = vmm_devtree_addnode(cnode, hpet_nm);

            BUG_ON(nnode == NULL);

            if (vmm_devtree_setattr(nnode, VMM_DEVTREE_HPET_ID_ATTR_NAME,
                                    &hpet->tmr_blks[i].asid,
                                    VMM_DEVTREE_ATTRTYPE_UINT32,
                                    sizeof(hpet->tmr_blks[i].asid), FALSE) != VMM_OK) {
                return VMM_EFAIL;
            }

            if (vmm_devtree_setattr(nnode, VMM_DEVTREE_HPET_PADDR_ATTR_NAME,
                                    &hpet->tmr_blks[i].base, VMM_DEVTREE_ATTRTYPE_PHYSADDR,
                                    sizeof(physical_addr_t), FALSE) != VMM_OK) {
                return VMM_EFAIL;
            }
        }
    }

    return VMM_OK;
}
static int __init acpi_populate_lapic_devtree(struct acpi_madt_hdr *madt_hdr,
        struct vmm_devtree_node *cnode)
{
    unsigned int idx = 0;
    int ret = VMM_OK;
    struct acpi_madt_lapic *lapic;
    char lapic_nm[256];

    for (;;) {
        lapic = (struct acpi_madt_lapic *)
                acpi_madt_get_typed_item(madt_hdr, ACPI_MADT_TYPE_LAPIC,
                                         idx);
        if (!lapic)
            break;

        memset(lapic_nm, 0, sizeof(lapic_nm));
        vmm_sprintf(lapic_nm, VMM_DEVTREE_LAPIC_PCPU_NODE_FMT, idx);
        struct vmm_devtree_node *nnode = vmm_devtree_addnode(cnode, lapic_nm);

        if (vmm_devtree_setattr(nnode, VMM_DEVTREE_LAPIC_CPU_ID_ATTR_NAME,
                                &lapic->acpi_cpu_id, VMM_DEVTREE_ATTRTYPE_UINT32,
                                sizeof(lapic->acpi_cpu_id), FALSE) != VMM_OK) {
            ret = VMM_EFAIL;
            break;
        }

        if (vmm_devtree_setattr(nnode, VMM_DEVTREE_LAPIC_LAPIC_ID_ATTR_NAME,
                                &lapic->apic_id, VMM_DEVTREE_ATTRTYPE_UINT32,
                                sizeof(lapic->apic_id), FALSE) != VMM_OK) {
            ret = VMM_EFAIL;
            break;
        }

        idx++;
    }

    vmm_devtree_setattr(cnode, VMM_DEVTREE_NR_LAPIC_ATTR_NAME,
                        &idx, VMM_DEVTREE_ATTRTYPE_UINT32, sizeof(idx), FALSE);

    return ret;
}
static int __init acpi_populate_ioapic_devtree(struct acpi_madt_hdr *madt_hdr,
        struct vmm_devtree_node *cnode)
{
    unsigned int idx = 0;
    int ret = VMM_OK;
    struct acpi_madt_ioapic *ioapic;
    char ioapic_nm[256];

    for (;;) {
        ioapic = (struct acpi_madt_ioapic *)
                 acpi_madt_get_typed_item(madt_hdr, ACPI_MADT_TYPE_IOAPIC,
                                          idx);
        if (!ioapic)
            break;

        memset(ioapic_nm, 0, sizeof(ioapic_nm));
        vmm_sprintf(ioapic_nm, VMM_DEVTREE_IOAPIC_NODE_FMT, idx);
        struct vmm_devtree_node *nnode = vmm_devtree_addnode(cnode, ioapic_nm);

        if (vmm_devtree_setattr(nnode, VMM_DEVTREE_IOAPIC_PADDR_ATTR_NAME,
                                &ioapic->address, VMM_DEVTREE_ATTRTYPE_PHYSADDR,
                                sizeof(physical_addr_t), FALSE) != VMM_OK) {
            ret = VMM_EFAIL;
            break;
        }

        if (vmm_devtree_setattr(nnode, VMM_DEVTREE_IOAPIC_GINT_BASE_ATTR_NAME,
                                &ioapic->global_int_base, VMM_DEVTREE_ATTRTYPE_UINT32,
                                sizeof(ioapic->global_int_base), FALSE) != VMM_OK) {
            ret = VMM_EFAIL;
            break;
        }

        idx++;
    }

    vmm_devtree_setattr(cnode, VMM_DEVTREE_NR_IOAPIC_ATTR_NAME,
                        &idx, VMM_DEVTREE_ATTRTYPE_UINT32, sizeof(idx), FALSE);

    return ret;
}
Beispiel #4
0
int initrd_devtree_update(u64 start, u64 end)
{
	int rc = VMM_OK;
	struct vmm_devtree_node *node;

	/* Sanity checks */
	if (start >= end) {
		return VMM_EINVALID;
	}
	if (initrd_rbd) {
		return VMM_EBUSY;
	}

	/* There should be a /chosen node */
	node = vmm_devtree_getnode(VMM_DEVTREE_PATH_SEPARATOR_STRING
				   VMM_DEVTREE_CHOSEN_NODE_NAME);
	if (!node) {
		return VMM_ENODEV;
	}

	/* Update start attribute in /chosen node */
	rc = vmm_devtree_setattr(node, INITRD_START_ATTR2_NAME,
				 &start, VMM_DEVTREE_ATTRTYPE_UINT64,
				 sizeof(start), FALSE);
	if (rc) {
		goto done;
	}

	/* Update end attribute in /chosen node */
	rc = vmm_devtree_setattr(node, INITRD_END_ATTR2_NAME,
				 &end, VMM_DEVTREE_ATTRTYPE_UINT64,
				 sizeof(end), FALSE);
	if (rc) {
		goto done;
	}

done:
	vmm_devtree_dref_node(node);

	return rc;
}
Beispiel #5
0
static void libfdt_parse_devtree_recursive(struct fdt_fileinfo * fdt,
					   struct vmm_devtree_node * node,
					   char **data)
{
	u32 type, len;
	const char * name;
	struct vmm_devtree_node *child;

	if (!fdt || !node) {
		return;
	}

	while (LIBFDT_DATA32(*data) != FDT_END_NODE) {
		switch (LIBFDT_DATA32(*data)) {
		case FDT_PROP:
			*data += sizeof(fdt_cell_t);
			len = LIBFDT_DATA32(*data);
			*data += sizeof(fdt_cell_t);
			name = &fdt->str[LIBFDT_DATA32(*data)];
			*data += sizeof(fdt_cell_t);
			type = vmm_devtree_estimate_attrtype(name);
			vmm_devtree_setattr(node, name, *data, type, len);
			*data += len;
			while ((virtual_addr_t) (*data) % sizeof(fdt_cell_t) != 0)
				(*data)++;
			break;
		case FDT_NOP:
			*data += sizeof(fdt_cell_t);
			break;
		case FDT_BEGIN_NODE:
			*data += sizeof(fdt_cell_t);
			type = VMM_DEVTREE_NODETYPE_UNKNOWN;
			child = vmm_devtree_addnode(node, *data, type, NULL);
			*data += vmm_strlen(*data) + 1;
			while ((virtual_addr_t) (*data) % sizeof(fdt_cell_t) != 0) {
				(*data)++;
			}
			libfdt_parse_devtree_recursive(fdt, child, data);
			break;
		default:
			return;
			break;
		};
	}

	*data += sizeof(fdt_cell_t);

	return;
}
Beispiel #6
0
static int cmd_vfs_fdt_load(struct vmm_chardev *cdev,
			    const char *devtree_path,
			    const char *devtree_root_name,
			    const char *path,
			    int aliasc, char **aliasv)
{
	int a, fd, rc = VMM_OK;
	char *astr;
	const char *aname, *apath, *aattr, *atype;
	size_t fdt_rd;
	void *fdt_data, *val = NULL;
	u32 val_type, val_len = 0;
	struct stat st;
	struct vmm_devtree_node *root, *anode, *node;
	struct vmm_devtree_node *parent;
	struct fdt_fileinfo fdt;

	parent = vmm_devtree_getnode(devtree_path);
	if (!parent) {
		vmm_cprintf(cdev, "Devtree path %s does not exist.\n",
			    devtree_path);
		return VMM_EINVALID;
	}

	root = vmm_devtree_getchild(parent, devtree_root_name);
	if (root) {
		vmm_devtree_dref_node(root);
		vmm_cprintf(cdev, "Devtree path %s/%s already exist.\n",
			    devtree_path, devtree_root_name);
		rc = VMM_EINVALID;
		goto fail;
	}

	fd = vfs_open(path, O_RDONLY, 0);
	if (fd < 0) {
		vmm_cprintf(cdev, "Failed to open %s\n", path);
		rc = fd;
		goto fail;
	}

	rc = vfs_fstat(fd, &st);
	if (rc) {
		vmm_cprintf(cdev, "Path %s does not exist.\n", path);
		goto fail_closefd;
	}

	if (!(st.st_mode & S_IFREG)) {
		vmm_cprintf(cdev, "Path %s should be regular file.\n", path);
		rc = VMM_EINVALID;
		goto fail_closefd;
	}

	if (!st.st_size) {
		vmm_cprintf(cdev, "File %s has zero %d bytes.\n", path);
		rc = VMM_EINVALID;
		goto fail_closefd;
	}

	if (st.st_size > VFS_MAX_FDT_SZ) {
		vmm_cprintf(cdev, "File %s has size %d bytes (> %d bytes).\n",
			    path, (long)st.st_size, VFS_MAX_FDT_SZ);
		rc = VMM_EINVALID;
		goto fail_closefd;
	}

	fdt_data = vmm_zalloc(VFS_MAX_FDT_SZ);
	if (!fdt_data) {
		rc = VMM_ENOMEM;
		goto fail_closefd;
	}

	fdt_rd = vfs_read(fd, fdt_data, VFS_MAX_FDT_SZ);
	if (fdt_rd < st.st_size) {
		rc = VMM_EIO;
		goto fail_freedata;
	}

	rc = libfdt_parse_fileinfo((virtual_addr_t)fdt_data, &fdt);
	if (rc) {
		goto fail_freedata;
	}

	root = NULL;
	rc = libfdt_parse_devtree(&fdt, &root, devtree_root_name, parent);
	if (rc) {
		goto fail_freedata;
	}

	anode = vmm_devtree_getchild(root, VMM_DEVTREE_ALIASES_NODE_NAME);

	for (a = 0; a < aliasc; a++) {
		if (!anode) {
			vmm_cprintf(cdev, "Error: %s node not available\n",
				    VMM_DEVTREE_ALIASES_NODE_NAME);
			continue;
		}

		astr = aliasv[a];

		aname = astr;
		while (*astr != '\0' && *astr != ',') {
			astr++;
		}
		if (*astr == ',') {
			*astr = '\0';
			astr++;
		}

		if (*astr == '\0') {
			continue;
		}
		aattr = astr;
		while (*astr != '\0' && *astr != ',') {
			astr++;
		}
		if (*astr == ',') {
			*astr = '\0';
			astr++;
		}

		if (*astr == '\0') {
			continue;
		}
		atype = astr;
		while (*astr != '\0' && *astr != ',') {
			astr++;
		}
		if (*astr == ',') {
			*astr = '\0';
			astr++;
		}

		if (*astr == '\0') {
			continue;
		}

		if (vmm_devtree_read_string(anode, aname, &apath)) {
			vmm_cprintf(cdev, "Error: Failed to read %s attribute "
				    "of %s node\n", aname,
				    VMM_DEVTREE_ALIASES_NODE_NAME);
			continue;
		}

		node = vmm_devtree_getchild(root, apath);
		if (!node) {
			vmm_cprintf(cdev, "Error: %s node not found under "
				    "%s/%s\n", apath, devtree_path,
				    devtree_root_name);
			continue;
		}

		if (!strcmp(atype, "unknown")) {
			val = NULL;
			val_len = 0;
			val_type = VMM_DEVTREE_MAX_ATTRTYPE;
		} else if (!strcmp(atype, "string")) {
			val_len = strlen(astr) + 1;
			val = vmm_zalloc(val_len);
			if (!val) {
				vmm_cprintf(cdev, "Error: vmm_zalloc(%d) "
					    "failed\n", val_len);
				goto next_iter;
			}
			strcpy(val, astr);
			val_type = VMM_DEVTREE_ATTRTYPE_STRING;
		} else if (!strcmp(atype, "bytes")) {
			val_len = 1;
			val = vmm_zalloc(val_len);
			if (!val) {
				vmm_cprintf(cdev, "Error: vmm_zalloc(%d) "
					    "failed\n", val_len);
				goto next_iter;
			}
			*((u8 *)val) = strtoul(astr, NULL, 0);
			val_type = VMM_DEVTREE_ATTRTYPE_BYTEARRAY;
		} else if (!strcmp(atype, "uint32")) {
			val_len = 4;
			val = vmm_zalloc(val_len);
			if (!val) {
				vmm_cprintf(cdev, "Error: vmm_zalloc(%d) "
					    "failed\n", val_len);
				goto next_iter;
			}
			*((u32 *)val) = strtoul(astr, NULL, 0);
			val_type = VMM_DEVTREE_ATTRTYPE_UINT32;
		} else if (!strcmp(atype, "uint64")) {
			val_len = 8;
			val = vmm_zalloc(val_len);
			if (!val) {
				vmm_cprintf(cdev, "Error: vmm_zalloc(%d) "
					    "failed\n", val_len);
				goto next_iter;
			}
			*((u64 *)val) = strtoull(astr, NULL, 0);
			val_type = VMM_DEVTREE_ATTRTYPE_UINT64;
		} else if (!strcmp(atype, "physaddr")) {
			val_len = sizeof(physical_addr_t);
			val = vmm_zalloc(val_len);
			if (!val) {
				vmm_cprintf(cdev, "Error: vmm_zalloc(%d) "
					    "failed\n", val_len);
				goto next_iter;
			}
			*((physical_addr_t *)val) = strtoull(astr, NULL, 0);
			val_type = VMM_DEVTREE_ATTRTYPE_PHYSADDR;
		} else if (!strcmp(atype, "physsize")) {
			val_len = sizeof(physical_size_t);
			val = vmm_zalloc(val_len);
			if (!val) {
				vmm_cprintf(cdev, "Error: vmm_zalloc(%d) "
					    "failed\n", val_len);
				goto next_iter;
			}
			*((physical_size_t *)val) = strtoull(astr, NULL, 0);
			val_type = VMM_DEVTREE_ATTRTYPE_PHYSSIZE;
		} else if (!strcmp(atype, "virtaddr")) {
			val_len = sizeof(virtual_addr_t);
			val = vmm_zalloc(val_len);
			if (!val) {
				vmm_cprintf(cdev, "Error: vmm_zalloc(%d) "
					    "failed\n", val_len);
				goto next_iter;
			}
			*((virtual_addr_t *)val) = strtoull(astr, NULL, 0);
			val_type = VMM_DEVTREE_ATTRTYPE_VIRTADDR;
		} else if (!strcmp(atype, "virtsize")) {
			val_len = sizeof(virtual_size_t);
			val = vmm_zalloc(val_len);
			if (!val) {
				vmm_cprintf(cdev, "Error: vmm_zalloc(%d) "
					    "failed\n", val_len);
				goto next_iter;
			}
			*((virtual_size_t *)val) = strtoull(astr, NULL, 0);
			val_type = VMM_DEVTREE_ATTRTYPE_VIRTSIZE;
		} else {
			vmm_cprintf(cdev, "Error: Invalid attribute type %s\n",
				    atype);
			goto next_iter;
		}

		if (val && (val_len > 0)) {
			vmm_devtree_setattr(node, aattr, val,
					    val_type, val_len, FALSE);
			vmm_free(val);
		}

next_iter:
		vmm_devtree_dref_node(node);
	}

	vmm_devtree_dref_node(anode);

fail_freedata:
	vmm_free(fdt_data);
fail_closefd:
	vfs_close(fd);
fail:
	vmm_devtree_dref_node(parent);
	return rc;
}
Beispiel #7
0
static void libfdt_parse_devtree_recursive(struct fdt_fileinfo *fdt,
					   struct vmm_devtree_node *node,
					   char **data)
{
	void *val;
	const char *name;
	u32 type, len, alen, addr_cells, size_cells;
	struct vmm_devtree_node *child;

	if (!fdt || !node) {
		return;
	}

	if (vmm_devtree_read_u32(node->parent,
				 "#address-cells", &addr_cells)) {
		addr_cells = sizeof(physical_addr_t) / sizeof(fdt_cell_t);
	}
	if (vmm_devtree_read_u32(node->parent,
				 "#size-cells", &size_cells)) {
		size_cells = sizeof(physical_size_t) / sizeof(fdt_cell_t);
	}

	while (LIBFDT_DATA32(*data) != FDT_END_NODE) {
		switch (LIBFDT_DATA32(*data)) {
		case FDT_PROP:
			*data += sizeof(fdt_cell_t);
			len = LIBFDT_DATA32(*data);
			*data += sizeof(fdt_cell_t);
			name = &fdt->str[LIBFDT_DATA32(*data)];
			*data += sizeof(fdt_cell_t);
			type = vmm_devtree_estimate_attrtype(name);
			alen = libfdt_property_len(name, addr_cells, 
						   size_cells, len);
			val = vmm_zalloc(alen);
			libfdt_property_read(name, val, *data,
					     addr_cells, size_cells, len);
			vmm_devtree_setattr(node, name, val, type, alen);
			vmm_free(val);
			*data += len;
			while ((virtual_addr_t) (*data) % sizeof(fdt_cell_t) != 0)
				(*data)++;
			break;
		case FDT_NOP:
			*data += sizeof(fdt_cell_t);
			break;
		case FDT_BEGIN_NODE:
			*data += sizeof(fdt_cell_t);
			child = vmm_devtree_addnode(node, *data);
			*data += strlen(*data) + 1;
			while ((virtual_addr_t) (*data) % sizeof(fdt_cell_t) != 0) {
				(*data)++;
			}
			libfdt_parse_devtree_recursive(fdt, child, data);
			break;
		default:
			return;
			break;
		};
	}

	*data += sizeof(fdt_cell_t);

	return;
}