/* * Increase node phandle by phandle_offset */ static void fdt_increase_phandle(void *fdtp, int node_offset, uint32_t phandle_offset) { int proplen; void *phandle_pos, *node_pos; node_pos = (char*)fdtp + node_offset; phandle_pos = fdt_getprop_w(fdtp, node_offset, "phandle", &proplen); if (phandle_pos) fdt_increase_u32(phandle_pos, phandle_offset); phandle_pos = fdt_getprop_w(fdtp, node_offset, "linux,phandle", &proplen); if (phandle_pos) fdt_increase_u32(phandle_pos, phandle_offset); }
/* Update portal containter to match LAW setup of portal in phy map */ void fdt_portal(void *blob, const char *compat, const char *container, u64 addr, u32 size) { int off; off = fdt_node_offset_by_compatible(blob, -1, compat); if (off < 0) return ; off = fdt_parent_offset(blob, off); /* if non-zero assume we have a container */ if (off > 0) { char buf[60]; const char *p, *name; u32 *range; int len; /* fixup ranges */ range = fdt_getprop_w(blob, off, "ranges", &len); if (range == NULL) { printf("ERROR: container for %s has no ranges", compat); return ; } range[0] = 0; if (len == 16) { range[1] = addr >> 32; range[2] = addr & 0xffffffff; range[3] = size; } else {
void fdt_fsl_mc_fixup_iommu_map_entry(void *blob) { u32 *prop; u32 iommu_map[4]; int offset; int lenp; /* find fsl-mc node */ offset = fdt_path_offset(blob, "/soc/fsl-mc"); if (offset < 0) offset = fdt_path_offset(blob, "/fsl-mc"); if (offset < 0) { printf("%s: fsl-mc: ERR: fsl-mc node not found in DT, err %d\n", __func__, offset); return; } prop = fdt_getprop_w(blob, offset, "iommu-map", &lenp); if (!prop) { debug("%s: fsl-mc: ERR: missing iommu-map in fsl-mc bus node\n", __func__); return; } iommu_map[0] = cpu_to_fdt32(FSL_DPAA2_STREAM_ID_START); iommu_map[1] = *++prop; iommu_map[2] = cpu_to_fdt32(FSL_DPAA2_STREAM_ID_START); iommu_map[3] = cpu_to_fdt32(FSL_DPAA2_STREAM_ID_END - FSL_DPAA2_STREAM_ID_START + 1); fdt_setprop_inplace(blob, offset, "iommu-map", iommu_map, sizeof(iommu_map)); }
static void cds_pci_fixup(void *blob) { int node; const char *path; int len, slot, i; u32 *map = NULL, *piccells = NULL; int off, cells; node = fdt_path_offset(blob, "/aliases"); if (node >= 0) { path = fdt_getprop(blob, node, "pci0", NULL); if (path) { node = fdt_path_offset(blob, path); if (node >= 0) { map = fdt_getprop_w(blob, node, "interrupt-map", &len); } /* Each item in "interrupt-map" property is translated with * following cells: * PCI #address-cells, PCI #interrupt-cells, * PIC address, PIC #address-cells, PIC #interrupt-cells. */ cells = fdt_getprop_u32_default(blob, path, "#address-cells", 1); cells += fdt_getprop_u32_default(blob, path, "#interrupt-cells", 1); off = fdt_node_offset_by_phandle(blob, fdt32_to_cpu(*(map+cells))); if (off <= 0) return; cells += 1; piccells = (u32 *)fdt_getprop(blob, off, "#address-cells", NULL); if (piccells == NULL) return; cells += *piccells; piccells = (u32 *)fdt_getprop(blob, off, "#interrupt-cells", NULL); if (piccells == NULL) return; cells += *piccells; } } if (map) { len /= sizeof(u32); slot = get_pci_slot(); for (i=0;i<len;i+=cells) { /* We rotate the interrupt pins so that the mapping * changes depending on the slot the carrier card is in. */ map[3] = ((map[3] + slot - 2) % 4) + 1; map+=cells; } } }
int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name, const void *val, int len) { void *propval; int proplen; propval = fdt_getprop_w(fdt, nodeoffset, name, &proplen); if (! propval) return proplen; if (proplen != len) return -FDT_ERR_NOSPACE; memcpy(propval, val, len); return 0; }
static __init u64 get_kaslr_seed(void *fdt) { int node, len; fdt64_t *prop; u64 ret; node = fdt_path_offset(fdt, "/chosen"); if (node < 0) return 0; prop = fdt_getprop_w(fdt, node, "kaslr-seed", &len); if (!prop || len != sizeof(u64)) return 0; ret = fdt64_to_cpu(*prop); *prop = 0; return ret; }
/* * Handle __local_fixups__ node in overlay DTB */ static int fdt_overlay_do_local_fixups(void *main_fdtp, void *overlay_fdtp) { int overlay_local_fixups_o; int len; const char *fixups; uint32_t phandle_offset; overlay_local_fixups_o = fdt_path_offset(overlay_fdtp, "/__local_fixups__"); if (overlay_local_fixups_o < 0) return (-1); phandle_offset = fdt_max_phandle(main_fdtp); fdt_increase_phandles(overlay_fdtp, phandle_offset); fixups = fdt_getprop_w(overlay_fdtp, overlay_local_fixups_o, "fixup", &len); if (fixups) { if (fdt_do_local_fixup(overlay_fdtp, fixups, len, phandle_offset) < 0) return (-1); } return (0); }
/* * Returns exact memory location specified by fixup in format * /path/to/node:property:offset */ static void * fdt_get_fixup_location(void *fdtp, const char *fixup) { char *path, *prop, *offsetp, *endp; int prop_offset, o, proplen; void *result; result = 0; path = strdup(fixup); prop = strchr(path, ':'); if (prop == NULL) { printf("missing property part in \"%s\"\n", fixup); result = NULL; goto out; } *prop = 0; prop++; offsetp = strchr(prop, ':'); if (offsetp == NULL) { printf("missing offset part in \"%s\"\n", fixup); result = NULL; goto out; } *offsetp = 0; offsetp++; prop_offset = strtoul(offsetp, &endp, 10); if (*endp != '\0') { printf("\"%s\" is not valid number\n", offsetp); result = NULL; goto out; } o = fdt_path_offset(fdtp, path); if (o < 0) { printf("path \"%s\" not found\n", path); result = NULL; goto out; } result = fdt_getprop_w(fdtp, o, prop, &proplen); if (result == NULL){ printf("property \"%s\" not found in \"%s\" node\n", prop, path); result = NULL; goto out; } if (proplen < prop_offset + sizeof(uint32_t)) { printf("%s: property length is too small for fixup\n", fixup); result = NULL; goto out; } result = (char*)result + prop_offset; out: free(path); return (result); }