static void *_fdt_grab_space(void *fdt, int len) { int offset = fdt_size_dt_struct(fdt); int spaceleft; spaceleft = fdt_totalsize(fdt) - fdt_off_dt_struct(fdt) - fdt_size_dt_strings(fdt); if ((offset + len < offset) || (offset + len > spaceleft)) return NULL; fdt_set_size_dt_struct(fdt, offset + len); return fdt_offset_ptr_w(fdt, offset, len); }
/** * dump_fdt_regions() - Dump regions of an FDT as binary data * * This dumps an FDT as binary, but only certain regions of it. This is the * final stage of the grep - we have a list of regions we want to dump, * and this function dumps them. * * The output of this function may or may not be a valid FDT. To ensure it * is, these disp->flags must be set: * * FDT_REG_SUPERNODES: ensures that subnodes are preceeded by their * parents. Without this option, fragments of subnode data may be * output without the supernodes above them. This is useful for * hashing but cannot produce a valid FDT. * FDT_REG_ADD_STRING_TAB: Adds a string table to the end of the FDT. * Without this none of the properties will have names * FDT_REG_ADD_MEM_RSVMAP: Adds a mem_rsvmap table - an FDT is invalid * without this. * * @disp: Display structure, holding info about our options * @blob: FDT blob to display * @region: List of regions to display * @count: Number of regions * @out: Output destination */ static int dump_fdt_regions(struct display_info *disp, const void *blob, struct fdt_region region[], int count, char *out) { struct fdt_header *fdt; int size, struct_start; int ptr; int i; /* Set up a basic header (even if we don't actually write it) */ fdt = (struct fdt_header *)out; memset(fdt, '\0', sizeof(*fdt)); fdt_set_magic(fdt, FDT_MAGIC); struct_start = FDT_ALIGN(sizeof(struct fdt_header), sizeof(struct fdt_reserve_entry)); fdt_set_off_mem_rsvmap(fdt, struct_start); fdt_set_version(fdt, FDT_LAST_SUPPORTED_VERSION); fdt_set_last_comp_version(fdt, FDT_FIRST_SUPPORTED_VERSION); /* * Calculate the total size of the regions we are writing out. The * first will be the mem_rsvmap if the FDT_REG_ADD_MEM_RSVMAP flag * is set. The last will be the string table if FDT_REG_ADD_STRING_TAB * is set. */ for (i = size = 0; i < count; i++) size += region[i].size; /* Bring in the mem_rsvmap section from the old file if requested */ if (count > 0 && (disp->flags & FDT_REG_ADD_MEM_RSVMAP)) { struct_start += region[0].size; size -= region[0].size; } fdt_set_off_dt_struct(fdt, struct_start); /* Update the header to have the correct offsets/sizes */ if (count >= 2 && (disp->flags & FDT_REG_ADD_STRING_TAB)) { int str_size; str_size = region[count - 1].size; fdt_set_size_dt_struct(fdt, size - str_size); fdt_set_off_dt_strings(fdt, struct_start + size - str_size); fdt_set_size_dt_strings(fdt, str_size); fdt_set_totalsize(fdt, struct_start + size); } /* Write the header if required */ ptr = 0; if (disp->header) { ptr = sizeof(*fdt); while (ptr < fdt_off_mem_rsvmap(fdt)) out[ptr++] = '\0'; } /* Output all the nodes including any mem_rsvmap/string table */ for (i = 0; i < count; i++) { struct fdt_region *reg = ®ion[i]; memcpy(out + ptr, (const char *)blob + reg->offset, reg->size); ptr += reg->size; } return ptr; }