int arch_board_ram_size(physical_size_t * size) { int rc = VMM_OK; struct fdt_fileinfo fdt; struct fdt_node_header * fdt_node; struct fdt_property * prop; rc = libfdt_parse_fileinfo((virtual_addr_t) & dt_blob_start, &fdt); if (rc) { return rc; } fdt_node = libfdt_find_node(&fdt, VMM_DEVTREE_PATH_SEPARATOR_STRING VMM_DEVTREE_HOSTINFO_NODE_NAME VMM_DEVTREE_PATH_SEPARATOR_STRING VMM_DEVTREE_MEMORY_NODE_NAME); if (!fdt_node) { return VMM_EFAIL; } prop = libfdt_get_property(&fdt, fdt_node, VMM_DEVTREE_MEMORY_PHYS_SIZE_ATTR_NAME); if (!prop) { return VMM_EFAIL; } *size = *((physical_size_t *)prop->data); return VMM_OK; }
int arch_devtree_reserve_size(u32 index, physical_size_t *size) { u64 tmp; int rc = VMM_OK; struct fdt_fileinfo fdt; if (load_bank_resv_sz) { if (index == 0) { *size = load_bank_resv_sz; return VMM_OK; } else { index -= 1; } } rc = libfdt_parse_fileinfo((virtual_addr_t)&dt_blob_start, &fdt); if (rc) { return rc; } rc = libfdt_reserve_size(&fdt, index, &tmp); if (rc) { return rc; } *size = (physical_size_t)tmp; return VMM_OK; }
int arch_board_ram_start(physical_addr_t * addr) { int rc = VMM_OK; struct fdt_fileinfo fdt; struct fdt_node_header * fdt_node = NULL; struct fdt_property * prop = NULL; physical_addr_t *phys_adr = NULL; rc = libfdt_parse_fileinfo((virtual_addr_t) & dt_blob_start, &fdt); if (rc) { return rc; } fdt_node = libfdt_find_node(&fdt, VMM_DEVTREE_PATH_SEPARATOR_STRING VMM_DEVTREE_HOSTINFO_NODE_NAME VMM_DEVTREE_PATH_SEPARATOR_STRING VMM_DEVTREE_MEMORY_NODE_NAME); if (!fdt_node) { return VMM_EFAIL; } prop = libfdt_get_property(&fdt, fdt_node, VMM_DEVTREE_MEMORY_PHYS_ADDR_ATTR_NAME); if (!prop) { return VMM_EFAIL; } phys_adr = (physical_addr_t *)prop->data; *addr = *phys_adr; return VMM_OK; }
int arch_devtree_ram_start(physical_addr_t *addr) { #if 0 int rc = VMM_OK; struct fdt_fileinfo fdt; struct fdt_node_header *fdt_node; physical_addr_t data[2]; rc = libfdt_parse_fileinfo((virtual_addr_t)&dt_blob_start, &fdt); if (rc) { return rc; } fdt_node = libfdt_find_node(&fdt, VMM_DEVTREE_PATH_SEPARATOR_STRING VMM_DEVTREE_MEMORY_NODE_NAME); if (!fdt_node) { return VMM_EFAIL; } rc = libfdt_get_property(&fdt, fdt_node, VMM_DEVTREE_REG_ATTR_NAME, data); if (rc) { return rc; } *addr = data[0]; #else *addr = 0x100000UL; #endif return VMM_OK; }
int arch_devtree_populate(struct vmm_devtree_node **root) { int rc = VMM_OK; struct fdt_fileinfo fdt; /* Parse skeletal FDT */ rc = libfdt_parse_fileinfo((virtual_addr_t) & dt_blob_start, &fdt); if (rc) { return rc; } /* Populate skeletal FDT */ rc = libfdt_parse_devtree(&fdt, root); if (rc) { return rc; } /* FIXME: Populate device tree from ACPI table */ #if CONFIG_ACPI /* * Initialize the ACPI table to help initialize * other devices. */ acpi_init(); #endif return VMM_OK; }
int arch_board_ram_start(physical_addr_t *addr) { int rc = VMM_OK; struct fdt_fileinfo fdt; struct fdt_node_header *fdt_node; *addr = 0xffffffff; if (libfdt_parse_fileinfo((virtual_addr_t) & dt_blob_start, &fdt)) { return VMM_EFAIL; } fdt_node = libfdt_find_node(&fdt, VMM_DEVTREE_PATH_SEPARATOR_STRING VMM_DEVTREE_HOSTINFO_NODE_NAME VMM_DEVTREE_PATH_SEPARATOR_STRING VMM_DEVTREE_MEMORY_NODE_NAME); if (!fdt_node) { return VMM_EFAIL; } rc = libfdt_get_property(&fdt, fdt_node, VMM_DEVTREE_MEMORY_PHYS_ADDR_ATTR_NAME, addr); if (rc) { return rc; } return VMM_OK; }
int arch_board_devtree_populate(struct vmm_devtree_node **root) { struct fdt_fileinfo fdt; if (libfdt_parse_fileinfo((virtual_addr_t) & dt_blob_start, &fdt)) { return VMM_EFAIL; } return libfdt_parse_devtree(&fdt, root); }
int arch_devtree_populate(struct vmm_devtree_node **root) { int rc = VMM_OK; struct fdt_fileinfo fdt; rc = libfdt_parse_fileinfo((virtual_addr_t)&dt_blob_start, &fdt); if (rc) { return rc; } return libfdt_parse_devtree(&fdt, root, "\0", NULL); }
int arch_devtree_reserve_count(u32 *count) { int rc = VMM_OK; struct fdt_fileinfo fdt; rc = libfdt_parse_fileinfo((virtual_addr_t)&dt_blob_start, &fdt); if (rc) { return rc; } *count = libfdt_reserve_count(&fdt); return VMM_OK; }
int arch_devtree_reserve_size(u32 index, physical_size_t *size) { u64 tmp; int rc = VMM_OK; struct fdt_fileinfo fdt; rc = libfdt_parse_fileinfo((virtual_addr_t)&dt_blob_start, &fdt); if (rc) { return rc; } rc = libfdt_reserve_size(&fdt, index, &tmp); if (rc) { return rc; } *size = (physical_size_t)tmp; return VMM_OK; }
int arch_devtree_ram_bank_setup(void) { int rc = VMM_OK; physical_addr_t tmp; struct match_info info; struct fdt_fileinfo fdt; struct fdt_node_header *fdt_root; struct fdt_node_header *fdt_node; u32 i, j, address_cells, size_cells; address_cells = sizeof(physical_addr_t) / sizeof(fdt_cell_t); size_cells = sizeof(physical_size_t) / sizeof(fdt_cell_t); rc = libfdt_parse_fileinfo((virtual_addr_t)&dt_blob_start, &fdt); if (rc) { return rc; } fdt_root = libfdt_find_node(&fdt, VMM_DEVTREE_PATH_SEPARATOR_STRING); if (!fdt_root) { return VMM_EFAIL; } rc = libfdt_get_property(&fdt, fdt_root, address_cells, size_cells, VMM_DEVTREE_ADDR_CELLS_ATTR_NAME, &i, sizeof(i)); if (!rc) { address_cells = i; } rc = libfdt_get_property(&fdt, fdt_root, address_cells, size_cells, VMM_DEVTREE_SIZE_CELLS_ATTR_NAME, &i, sizeof(i)); if (!rc) { size_cells = i; } info.fdt = &fdt; info.address_cells = address_cells; info.size_cells = size_cells; fdt_node = libfdt_find_matching_node(&fdt, match_memory_node, &info); if (!fdt_node) { return VMM_EFAIL; } rc = libfdt_get_property(&fdt, fdt_node, address_cells, size_cells, VMM_DEVTREE_ADDR_CELLS_ATTR_NAME, &i, sizeof(i)); if (!rc) { address_cells = i; } rc = libfdt_get_property(&fdt, fdt_node, address_cells, size_cells, VMM_DEVTREE_SIZE_CELLS_ATTR_NAME, &i, sizeof(i)); if (!rc) { size_cells = i; } memset(bank_data, 0, sizeof(bank_data)); memset(dt_bank_data, 0, sizeof(dt_bank_data)); rc = libfdt_get_property(&fdt, fdt_node, address_cells, size_cells, VMM_DEVTREE_REG_ATTR_NAME, dt_bank_data, sizeof(dt_bank_data)); if (rc) { return rc; } /* Remove Zero sized banks */ for (i = 0, j = 0 ; i < array_size(dt_bank_data); i += 2) { if (dt_bank_data[i + 1]) { bank_data[j] = dt_bank_data[i]; bank_data[j + 1] = dt_bank_data[i + 1]; j += 2; } } /* Count of RAM banks */ bank_nr = 0; for (i = 0; i < array_size(bank_data); i += 2) { if (bank_data[i+1]) { bank_nr++; } else { break; } } if (!bank_nr) { return VMM_OK; } /* Sort banks based on start address */ for (i = 0; i < (bank_nr - 1); i++) { for (j = i+1; j < bank_nr; j++) { if (bank_data[(2*i)] > bank_data[(2*j)]) { tmp = bank_data[(2*i)]; bank_data[(2*i)] = bank_data[(2*j)]; bank_data[(2*j)] = tmp; tmp = bank_data[(2*i)+1]; bank_data[(2*i)+1] = bank_data[(2*j)+1]; bank_data[(2*j)+1] = tmp; } } } /* * For quite a few RISC-V systems, the RUNTIME M-mode firmware * is located at start of a RAM bank. Unfortunately in most cases, * the DTB passed to Xvisor (or Linux) does not have memreserve * entry for the RUNTIME M-mode firmware. To be safe, we reserve * RAM from start of the RAM bank to location where Xvisor is * loaded in the RAM bank. */ load_bank_nr = 0; load_bank_resv_pa = 0; load_bank_resv_sz = 0; for (i = 0; i < bank_nr; i++) { if (bank_data[2*i] <= arch_code_paddr_start() && arch_code_paddr_start() < (bank_data[2*i] + bank_data[2*i + 1])) { load_bank_nr = i; load_bank_resv_pa = bank_data[2*i]; load_bank_resv_sz = arch_code_paddr_start() - bank_data[2*i]; break; } } return VMM_OK; }
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; }
int arch_devtree_ram_start(physical_addr_t *addr) { int rc = VMM_OK; struct fdt_fileinfo fdt; struct fdt_node_header *fdt_root; struct fdt_node_header *fdt_node; u32 tmp, address_cells, size_cells; physical_addr_t data[2]; address_cells = sizeof(physical_addr_t) / sizeof(fdt_cell_t); size_cells = sizeof(physical_size_t) / sizeof(fdt_cell_t); rc = libfdt_parse_fileinfo((virtual_addr_t)&dt_blob_start, &fdt); if (rc) { return rc; } fdt_root = libfdt_find_node(&fdt, VMM_DEVTREE_PATH_SEPARATOR_STRING); if (!fdt_root) { return VMM_EFAIL; } rc = libfdt_get_property(&fdt, fdt_root, address_cells, size_cells, VMM_DEVTREE_ADDR_CELLS_ATTR_NAME, &tmp, sizeof(tmp)); if (!rc) { address_cells = tmp; } rc = libfdt_get_property(&fdt, fdt_root, address_cells, size_cells, VMM_DEVTREE_SIZE_CELLS_ATTR_NAME, &tmp, sizeof(tmp)); if (!rc) { size_cells = tmp; } fdt_node = libfdt_find_node(&fdt, VMM_DEVTREE_PATH_SEPARATOR_STRING VMM_DEVTREE_MEMORY_NODE_NAME); if (!fdt_node) { return VMM_EFAIL; } rc = libfdt_get_property(&fdt, fdt_node, address_cells, size_cells, VMM_DEVTREE_ADDR_CELLS_ATTR_NAME, &tmp, sizeof(tmp)); if (!rc) { address_cells = tmp; } rc = libfdt_get_property(&fdt, fdt_node, address_cells, size_cells, VMM_DEVTREE_SIZE_CELLS_ATTR_NAME, &tmp, sizeof(tmp)); if (!rc) { size_cells = tmp; } rc = libfdt_get_property(&fdt, fdt_node, address_cells, size_cells, VMM_DEVTREE_REG_ATTR_NAME, data, sizeof(data)); if (rc) { return rc; } *addr = data[0]; return VMM_OK; }