Ejemplo n.º 1
0
int fdt_resize(void *fdt, void *buf, int bufsize)
{
	size_t headsize, tailsize;
	char *oldtail, *newtail;

	FDT_SW_CHECK_HEADER(fdt);

	headsize = fdt_off_dt_struct(fdt);
	tailsize = fdt_size_dt_strings(fdt);

	if ((headsize + tailsize) > bufsize)
		return -FDT_ERR_NOSPACE;

	oldtail = (char *)fdt + fdt_totalsize(fdt) - tailsize;
	newtail = (char *)buf + bufsize - tailsize;

	/* Two cases to avoid clobbering data if the old and new
	 * buffers partially overlap */
	if (buf <= fdt) {
		memmove(buf, fdt, headsize);
		memmove(newtail, oldtail, tailsize);
	} else {
		memmove(newtail, oldtail, tailsize);
		memmove(buf, fdt, headsize);
	}

	fdt_set_off_dt_strings(buf, bufsize);
	fdt_set_totalsize(buf, bufsize);

	return 0;
}
Ejemplo n.º 2
0
Archivo: fdt_sw.c Proyecto: 274914765/C
int fdt_finish(void *fdt)
{
    int err = check_header_sw(fdt);
    char *p = (char *)fdt;
    uint32_t *end;
    int oldstroffset, newstroffset;
    uint32_t tag;
    int offset, nextoffset;

    if (err)
        return err;

    /* Add terminator */
    end = grab_space(fdt, sizeof(*end));
    if (! end)
        return -FDT_ERR_NOSPACE;
    *end = cpu_to_fdt32(FDT_END);

    /* Relocate the string table */
    oldstroffset = fdt_totalsize(fdt) - fdt_size_dt_strings(fdt);
    newstroffset = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt);
    memmove(p + newstroffset, p + oldstroffset, fdt_size_dt_strings(fdt));
    fdt_set_off_dt_strings(fdt, newstroffset);

    /* Walk the structure, correcting string offsets */
    offset = 0;
    while ((tag = fdt_next_tag(fdt, offset, &nextoffset)) != FDT_END) {
        if (tag == FDT_PROP) {
            struct fdt_property *prop =
                fdt_offset_ptr_w(fdt, offset, sizeof(*prop));
            int nameoff;

            if (! prop)
                return -FDT_ERR_BADSTRUCTURE;

            nameoff = fdt32_to_cpu(prop->nameoff);
            nameoff += fdt_size_dt_strings(fdt);
            prop->nameoff = cpu_to_fdt32(nameoff);
        }
        offset = nextoffset;
    }

    /* Finally, adjust the header */
    fdt_set_totalsize(fdt, newstroffset + fdt_size_dt_strings(fdt));
    fdt_set_magic(fdt, FDT_MAGIC);
    return 0;
}
Ejemplo n.º 3
0
int fdt_finish(void *fdt)
{
	char *p = (char *)fdt;
	uint32_t *end;
	int oldstroffset, newstroffset;
	uint32_t tag;
	int offset, nextoffset;

	FDT_SW_CHECK_HEADER(fdt);

	
	end = _fdt_grab_space(fdt, sizeof(*end));
	if (! end)
		return -FDT_ERR_NOSPACE;
	*end = cpu_to_fdt32(FDT_END);

	
	oldstroffset = fdt_totalsize(fdt) - fdt_size_dt_strings(fdt);
	newstroffset = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt);
	memmove(p + newstroffset, p + oldstroffset, fdt_size_dt_strings(fdt));
	fdt_set_off_dt_strings(fdt, newstroffset);

	
	offset = 0;
	while ((tag = fdt_next_tag(fdt, offset, &nextoffset)) != FDT_END) {
		if (tag == FDT_PROP) {
			struct fdt_property *prop =
				_fdt_offset_ptr_w(fdt, offset);
			int nameoff;

			nameoff = fdt32_to_cpu(prop->nameoff);
			nameoff += fdt_size_dt_strings(fdt);
			prop->nameoff = cpu_to_fdt32(nameoff);
		}
		offset = nextoffset;
	}
	if (nextoffset < 0)
		return nextoffset;

	
	fdt_set_totalsize(fdt, newstroffset + fdt_size_dt_strings(fdt));
	fdt_set_magic(fdt, FDT_MAGIC);
	return 0;
}
Ejemplo n.º 4
0
int fdt_create(void *buf, int bufsize)
{
	void *fdt = buf;

	if (bufsize < (int)sizeof(struct fdt_header))
		return -FDT_ERR_NOSPACE;

	memset(buf, 0, bufsize);

	fdt_set_magic(fdt, FDT_SW_MAGIC);
	fdt_set_version(fdt, FDT_LAST_SUPPORTED_VERSION);
	fdt_set_last_comp_version(fdt, FDT_FIRST_SUPPORTED_VERSION);
	fdt_set_totalsize(fdt,  bufsize);

	fdt_set_off_mem_rsvmap(fdt, FDT_ALIGN(sizeof(struct fdt_header),
					      sizeof(struct fdt_reserve_entry)));
	fdt_set_off_dt_struct(fdt, fdt_off_mem_rsvmap(fdt));
	fdt_set_off_dt_strings(fdt, bufsize);

	return 0;
}
Ejemplo n.º 5
0
/**
 * 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 = &region[i];

		memcpy(out + ptr, (const char *)blob + reg->offset, reg->size);
		ptr += reg->size;
	}

	return ptr;
}