X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=lib%2Ffdtdec.c;h=7c7e673aeb79e975f0a725967eb298da4212d99d;hb=1fc4e6f486cc1e9d2dcf0ba86e6021c3d83dce51;hp=eb5aa20526fd509618311fdb3b4aab3c6379d46d;hpb=f2c8d7f591e28d3437155c7a6eae8c8d9e3fe552;p=oweals%2Fu-boot.git diff --git a/lib/fdtdec.c b/lib/fdtdec.c index eb5aa20526..7c7e673aeb 100644 --- a/lib/fdtdec.c +++ b/lib/fdtdec.c @@ -70,6 +70,11 @@ static const char * const compat_names[COMPAT_COUNT] = { COMPAT(SANDBOX_LCD_SDL, "sandbox,lcd-sdl"), COMPAT(TI_TPS65090, "ti,tps65090"), COMPAT(COMPAT_NXP_PTN3460, "nxp,ptn3460"), + COMPAT(SAMSUNG_EXYNOS_SYSMMU, "samsung,sysmmu-v3.3"), + COMPAT(PARADE_PS8625, "parade,ps8625"), + COMPAT(COMPAT_INTEL_LPC, "intel,lpc"), + COMPAT(INTEL_MICROCODE, "intel,microcode"), + COMPAT(MEMORY_SPD, "memory-spd"), }; const char *fdtdec_get_compatible(enum fdt_compat_id id) @@ -352,9 +357,9 @@ int fdtdec_get_alias_seq(const void *blob, const char *base, int offset, slash = strrchr(prop, '/'); if (strcmp(slash + 1, find_name)) continue; - for (p = name; *p; p++) { - if (isdigit(*p)) { - *seqp = simple_strtoul(p, NULL, 10); + for (p = name + strlen(name) - 1; p > name; p--) { + if (!isdigit(*p)) { + *seqp = simple_strtoul(p + 1, NULL, 10); debug("Found seq %d\n", *seqp); return 0; } @@ -380,6 +385,21 @@ int fdtdec_get_alias_node(const void *blob, const char *name) return fdt_path_offset(blob, prop); } +int fdtdec_get_chosen_node(const void *blob, const char *name) +{ + const char *prop; + int chosen_node; + int len; + + if (!blob) + return -FDT_ERR_NOTFOUND; + chosen_node = fdt_path_offset(blob, "/chosen"); + prop = fdt_getprop(blob, chosen_node, name, &len); + if (!prop) + return -FDT_ERR_NOTFOUND; + return fdt_path_offset(blob, prop); +} + int fdtdec_check_fdt(void) { /* @@ -467,6 +487,26 @@ int fdtdec_get_int_array(const void *blob, int node, const char *prop_name, return err; } +int fdtdec_get_int_array_count(const void *blob, int node, + const char *prop_name, u32 *array, int count) +{ + const u32 *cell; + int len, elems; + int i; + + debug("%s: %s\n", __func__, prop_name); + cell = fdt_getprop(blob, node, prop_name, &len); + if (!cell) + return -FDT_ERR_NOTFOUND; + elems = len / sizeof(u32); + if (count > elems) + count = elems; + for (i = 0; i < count; i++) + array[i] = fdt32_to_cpu(cell[i]); + + return count; +} + const u32 *fdtdec_locate_array(const void *blob, int node, const char *prop_name, int count) { @@ -651,20 +691,25 @@ char *fdtdec_get_config_string(const void *blob, const char *prop_name) return (char *)nodep; } -int fdtdec_decode_region(const void *blob, int node, - const char *prop_name, void **ptrp, size_t *size) +int fdtdec_decode_region(const void *blob, int node, const char *prop_name, + fdt_addr_t *basep, fdt_size_t *sizep) { const fdt_addr_t *cell; int len; - debug("%s: %s\n", __func__, prop_name); + debug("%s: %s: %s\n", __func__, fdt_get_name(blob, node, NULL), + prop_name); cell = fdt_getprop(blob, node, prop_name, &len); - if (!cell || (len != sizeof(fdt_addr_t) * 2)) + if (!cell || (len < sizeof(fdt_addr_t) * 2)) { + debug("cell=%p, len=%d\n", cell, len); return -1; + } + + *basep = fdt_addr_to_cpu(*cell); + *sizep = fdt_size_to_cpu(cell[1]); + debug("%s: base=%08lx, size=%lx\n", __func__, (ulong)*basep, + (ulong)*sizep); - *ptrp = map_sysmem(fdt_addr_to_cpu(*cell), *size); - *size = fdt_size_to_cpu(cell[1]); - debug("%s: size=%zx\n", __func__, *size); return 0; } @@ -680,6 +725,7 @@ int fdtdec_decode_region(const void *blob, int node, int fdtdec_read_fmap_entry(const void *blob, int node, const char *name, struct fmap_entry *entry) { + const char *prop; u32 reg[2]; if (fdtdec_get_int_array(blob, node, "reg", reg, 2)) { @@ -688,6 +734,145 @@ int fdtdec_read_fmap_entry(const void *blob, int node, const char *name, } entry->offset = reg[0]; entry->length = reg[1]; + entry->used = fdtdec_get_int(blob, node, "used", entry->length); + prop = fdt_getprop(blob, node, "compress", NULL); + entry->compress_algo = prop && !strcmp(prop, "lzo") ? + FMAP_COMPRESS_LZO : FMAP_COMPRESS_NONE; + prop = fdt_getprop(blob, node, "hash", &entry->hash_size); + entry->hash_algo = prop ? FMAP_HASH_SHA256 : FMAP_HASH_NONE; + entry->hash = (uint8_t *)prop; + + return 0; +} + +static u64 fdtdec_get_number(const fdt32_t *ptr, unsigned int cells) +{ + u64 number = 0; + + while (cells--) + number = (number << 32) | fdt32_to_cpu(*ptr++); + + return number; +} + +int fdt_get_resource(const void *fdt, int node, const char *property, + unsigned int index, struct fdt_resource *res) +{ + const fdt32_t *ptr, *end; + int na, ns, len, parent; + unsigned int i = 0; + + parent = fdt_parent_offset(fdt, node); + if (parent < 0) + return parent; + + na = fdt_address_cells(fdt, parent); + ns = fdt_size_cells(fdt, parent); + + ptr = fdt_getprop(fdt, node, property, &len); + if (!ptr) + return len; + + end = ptr + len / sizeof(*ptr); + + while (ptr + na + ns <= end) { + if (i == index) { + res->start = res->end = fdtdec_get_number(ptr, na); + res->end += fdtdec_get_number(&ptr[na], ns) - 1; + return 0; + } + + ptr += na + ns; + i++; + } + + return -FDT_ERR_NOTFOUND; +} + +int fdt_get_named_resource(const void *fdt, int node, const char *property, + const char *prop_names, const char *name, + struct fdt_resource *res) +{ + int index; + + index = fdt_find_string(fdt, node, prop_names, name); + if (index < 0) + return index; + + return fdt_get_resource(fdt, node, property, index, res); +} + +int fdtdec_pci_get_bdf(const void *fdt, int node, int *bdf) +{ + const fdt32_t *prop; + int len; + + prop = fdt_getprop(fdt, node, "reg", &len); + if (!prop) + return len; + + *bdf = fdt32_to_cpu(*prop) & 0xffffff; + + return 0; +} + +int fdtdec_decode_memory_region(const void *blob, int config_node, + const char *mem_type, const char *suffix, + fdt_addr_t *basep, fdt_size_t *sizep) +{ + char prop_name[50]; + const char *mem; + fdt_size_t size, offset_size; + fdt_addr_t base, offset; + int node; + + if (config_node == -1) { + config_node = fdt_path_offset(blob, "/config"); + if (config_node < 0) { + debug("%s: Cannot find /config node\n", __func__); + return -ENOENT; + } + } + if (!suffix) + suffix = ""; + + snprintf(prop_name, sizeof(prop_name), "%s-memory%s", mem_type, + suffix); + mem = fdt_getprop(blob, config_node, prop_name, NULL); + if (!mem) { + debug("%s: No memory type for '%s', using /memory\n", __func__, + prop_name); + mem = "/memory"; + } + + node = fdt_path_offset(blob, mem); + if (node < 0) { + debug("%s: Failed to find node '%s': %s\n", __func__, mem, + fdt_strerror(node)); + return -ENOENT; + } + + /* + * Not strictly correct - the memory may have multiple banks. We just + * use the first + */ + if (fdtdec_decode_region(blob, node, "reg", &base, &size)) { + debug("%s: Failed to decode memory region %s\n", __func__, + mem); + return -EINVAL; + } + + snprintf(prop_name, sizeof(prop_name), "%s-offset%s", mem_type, + suffix); + if (fdtdec_decode_region(blob, config_node, prop_name, &offset, + &offset_size)) { + debug("%s: Failed to decode memory region '%s'\n", __func__, + prop_name); + return -EINVAL; + } + + *basep = base + offset; + *sizep = offset_size; return 0; }