Пример #1
0
/* VPN_recv */
int32_t VPN_recv(int32_t fd, Buffer * buffer, uint32_t size, uint32_t flags)
{
	int32_t ret;

	if(_client_check(NULL, fd) == NULL)
		return -1;
#ifdef DEBUG
	fprintf(stderr, "DEBUG: %s(%d, buf, %u, %u)\n", __func__, fd, size,
			flags);
#endif
	if(buffer_set_size(buffer, size) != 0)
		return -1;
	/* FIXME implement flags */
	ret = recv(fd, buffer_get_data(buffer), size, 0);
#ifdef DEBUG
	fprintf(stderr, "DEBUG: %s(%d, buf, %u, %u) => %d\n", __func__, fd,
			size, flags, ret);
#endif
	if(buffer_set_size(buffer, (ret < 0) ? 0 : ret) != 0)
	{
		memset(buffer_get_data(buffer), 0, size);
		return -1;
	}
	return ret;
}
Пример #2
0
/* buffer_set */
int buffer_set(Buffer * buffer, size_t size, char * data)
{
	if(buffer_set_size(buffer, size) != 0)
		return -1;
	memcpy(buffer->data, data, size);
	return 0;
}
Пример #3
0
    DEFINE_FUNC_1(webp_decode_argb, data_buffer_value) {
        if (!val_is_buffer(data_buffer_value)) {
            val_throw(alloc_string("webp_decode_argb: Expected to be a buffer"));
            return alloc_null();
        }
        buffer data_buffer = val_to_buffer(data_buffer_value);
        int    data_len = buffer_size(data_buffer);
        char  *data_ptr = buffer_data(data_buffer);
        int webp_width = -1, webp_height = -1;
        char *webp_data_ptr = (char *)WebPDecodeARGB((const unsigned char *)data_ptr, data_len, &webp_width, &webp_height);
        int webp_data_len = webp_width * webp_height * 4;

        if (webp_data_ptr == NULL) {
            val_throw(alloc_string("webp_decode_argb: Invalid webp data"));
            return alloc_null();
        }

        buffer webp_buffer = alloc_buffer_len(0);
        buffer_append_sub(webp_buffer, webp_data_ptr, webp_data_len);
        buffer_set_size(webp_buffer, webp_data_len);

        value array = alloc_array(3);
        val_array_set_i(array, 0, alloc_int(webp_width));
        val_array_set_i(array, 1, alloc_int(webp_height));
        val_array_set_i(array, 2, buffer_val(webp_buffer));

        if (webp_data_ptr != NULL) free(webp_data_ptr);

        return array;
    }
Пример #4
0
/* buffer_set_data */
int buffer_set_data(Buffer * buffer, size_t offset, char * data, size_t size)
{
	if(offset + size > buffer->size) /* FIXME integer overflow */
		if(buffer_set_size(buffer, offset + size) != 0)
			return 1;
	memcpy(&buffer->data[offset], data, size);
	return 0;
}
Пример #5
0
	void Bytes::Resize (int size) {
		
		if (size != _length) {
			
			if (!_value) {
				
				_value = alloc_empty_object ();
				
			}
			
			if (val_is_null (val_field (_value, id_b))) {
				
				value dataValue;
				
				if (useBuffer) {
					
					buffer b = alloc_buffer_len (size);
					dataValue = buffer_val (b);
					_data = (unsigned char*)buffer_data (b);
					
				} else {
					
					dataValue = alloc_raw_string (size);
					_data = (unsigned char*)val_string (dataValue);
					
				}
				
				alloc_field (_value, id_b, dataValue);
				
			} else {
				
				if (useBuffer) {
					
					buffer b = val_to_buffer (val_field (_value, id_b));
					buffer_set_size (b, size);
					_data = (unsigned char*)buffer_data (b);
					
				} else {
					
					value s = alloc_raw_string (size);
					memcpy ((char *)val_string (s), val_string (val_field (_value, id_b)), size);
					alloc_field (_value, id_b, s);
					_data = (unsigned char*)val_string (s);
					
				}
				
			}
			
			alloc_field (_value, id_length, alloc_int (size));
			
		}
		
		_length = size;
		
	}
Пример #6
0
int appmessage_serialize(AppMessage * message, Buffer * buffer)
{
	Buffer * b;

	if((b = buffer_new(0, NULL)) == NULL)
		return -1;
	/* reset the output buffer */
	buffer_set_size(buffer, 0);
	if(_serialize_type(message, buffer, b) != 0)
		return -1;
	switch(message->type)
	{
		case AMT_ACKNOWLEDGEMENT:
			return _serialize_acknowledgement(message, buffer, b);
		case AMT_CALL:
			return _serialize_call(message, buffer, b);
		default:
			return -error_set_code(1, "%s%u",
					"Unable to serialize message type ",
					message->type);
	}
}
Пример #7
0
/**
 * \brief Prepares selector component for processing.
 * \param[in,out] dev Selector base component device.
 * \return Error code.
 */
static int selector_prepare(struct comp_dev *dev)
{
	struct comp_data *cd = comp_get_drvdata(dev);
	struct comp_buffer *sinkb;
	struct comp_buffer *sourceb;
	struct sof_ipc_comp_config *config = COMP_GET_CONFIG(dev);
	int ret;

	trace_selector("selector_prepare()");

	ret = comp_set_state(dev, COMP_TRIGGER_PREPARE);
	if (ret < 0)
		return ret;

	if (ret == COMP_STATUS_STATE_ALREADY_SET)
		return PPL_STATUS_PATH_STOP;

	/* selector component will have 1 source and 1 sink buffer */
	sourceb = list_first_item(&dev->bsource_list, struct comp_buffer,
				  sink_list);
	sinkb = list_first_item(&dev->bsink_list, struct comp_buffer,
				source_list);

	/* get source data format and period bytes */
	comp_set_period_bytes(sourceb->source, dev->frames, &cd->source_format,
			      &cd->source_period_bytes);

	/* get sink data format and period bytes */
	comp_set_period_bytes(sinkb->sink, dev->frames, &cd->sink_format,
			      &cd->sink_period_bytes);

	/* There is an assumption that sink component will report out
	 * proper number of channels [1] for selector to actually
	 * reduce channel count between source and sink
	 */
	trace_selector("selector_prepare(): source->params.channels = %u",
		       sourceb->sink->params.channels);
	trace_selector("selector_prepare(): sink->params.channels = %u",
		       sinkb->sink->params.channels);

	/* set downstream buffer size */
	ret = buffer_set_size(sinkb, cd->sink_period_bytes *
			      config->periods_sink);
	if (ret < 0) {
		trace_selector_error("selector_prepare() error: "
				     "buffer_set_size() failed");
		goto err;
	}

	/* validate */
	if (cd->sink_period_bytes == 0) {
		trace_selector_error("selector_prepare() error: "
				     "cd->sink_period_bytes = 0, dev->frames ="
				     " %u, sinkb->sink->frame_bytes = %u",
				     dev->frames, sinkb->sink->frame_bytes);
		ret = -EINVAL;
		goto err;
	}

	if (cd->source_period_bytes == 0) {
		trace_selector_error("selector_prepare() error: "
				     "cd->source_period_bytes = 0, "
				     "dev->frames = %u, "
				     "sourceb->source->frame_bytes = %u",
				     dev->frames,
				     sourceb->source->frame_bytes);
		ret = -EINVAL;
		goto err;
	}

	cd->sel_func = sel_get_processing_function(dev);
	if (!cd->sel_func) {
		trace_selector_error("selector_prepare() error: "
				     "invalid cd->sel_func, "
				     "cd->source_format = %u, "
				     "cd->sink_format = %u, "
				     "cd->out_channels_count = %u",
				     cd->source_format, cd->sink_format,
				     cd->config.out_channels_count);
		ret = -EINVAL;
		goto err;
	}

	return PPL_STATUS_PATH_STOP;

err:
	comp_set_state(dev, COMP_TRIGGER_RESET);
	return ret;
}
Пример #8
0
static int
write_elf(const struct rmod_context *ctx, const struct buffer *in,
          struct buffer *out)
{
	int ret;
	int bit64;
	size_t loc;
	size_t rmod_data_size;
	struct elf_writer *ew;
	struct buffer rmod_data;
	struct buffer rmod_header;
	struct buffer program;
	struct buffer relocs;
	Elf64_Xword total_size;
	Elf64_Addr addr;
	Elf64_Ehdr ehdr;

	bit64 = ctx->pelf.ehdr.e_ident[EI_CLASS] == ELFCLASS64;

	/*
	 * 3 sections will be added  to the ELF file.
	 * +------------------+
	 * |  rmodule header  |
	 * +------------------+
	 * |     program      |
	 * +------------------+
	 * |   relocations    |
	 * +------------------+
	 */

	/* Create buffer for header and relocations. */
	rmod_data_size = sizeof(struct rmodule_header);
	if (bit64)
		rmod_data_size += ctx->nrelocs * sizeof(Elf64_Addr);
	else
		rmod_data_size += ctx->nrelocs * sizeof(Elf32_Addr);

	if (buffer_create(&rmod_data, rmod_data_size, "rmod"))
		return -1;

	buffer_splice(&rmod_header, &rmod_data,
	              0, sizeof(struct rmodule_header));
	buffer_clone(&relocs, &rmod_data);
	buffer_seek(&relocs, sizeof(struct rmodule_header));

	/* Reset current location. */
	buffer_set_size(&rmod_header, 0);
	buffer_set_size(&relocs, 0);

	/* Program contents. */
	buffer_splice(&program, in, ctx->phdr->p_offset, ctx->phdr->p_filesz);

	/* Create ELF writer with modified entry point. */
	memcpy(&ehdr, &ctx->pelf.ehdr, sizeof(ehdr));
	ew = elf_writer_init(&ehdr);

	if (ew == NULL) {
		ERROR("Failed to create ELF writer.\n");
		buffer_delete(&rmod_data);
		return -1;
	}

	/* Write out rmodule_header. */
	ctx->xdr->put16(&rmod_header, RMODULE_MAGIC);
	ctx->xdr->put8(&rmod_header, RMODULE_VERSION_1);
	ctx->xdr->put8(&rmod_header, 0);
	/* payload_begin_offset */
	loc = sizeof(struct rmodule_header);
	ctx->xdr->put32(&rmod_header, loc);
	/* payload_end_offset */
	loc += ctx->phdr->p_filesz;
	ctx->xdr->put32(&rmod_header, loc);
	/* relocations_begin_offset */
	ctx->xdr->put32(&rmod_header, loc);
	/* relocations_end_offset */
	if (bit64)
		loc += ctx->nrelocs * sizeof(Elf64_Addr);
	else
		loc += ctx->nrelocs * sizeof(Elf32_Addr);
	ctx->xdr->put32(&rmod_header, loc);
	/* module_link_start_address */
	ctx->xdr->put32(&rmod_header, ctx->phdr->p_vaddr);
	/* module_program_size */
	ctx->xdr->put32(&rmod_header, ctx->phdr->p_memsz);
	/* module_entry_point */
	ctx->xdr->put32(&rmod_header, ctx->pelf.ehdr.e_entry);
	/* parameters_begin */
	ctx->xdr->put32(&rmod_header, ctx->parameters_begin);
	/* parameters_end */
	ctx->xdr->put32(&rmod_header, ctx->parameters_end);
	/* bss_begin */
	ctx->xdr->put32(&rmod_header, ctx->bss_begin);
	/* bss_end */
	ctx->xdr->put32(&rmod_header, ctx->bss_end);
	/* padding[4] */
	ctx->xdr->put32(&rmod_header, 0);
	ctx->xdr->put32(&rmod_header, 0);
	ctx->xdr->put32(&rmod_header, 0);
	ctx->xdr->put32(&rmod_header, 0);

	/* Write the relocations. */
	for (unsigned i = 0; i < ctx->nrelocs; i++) {
		if (bit64)
			ctx->xdr->put64(&relocs, ctx->emitted_relocs[i]);
		else
			ctx->xdr->put32(&relocs, ctx->emitted_relocs[i]);
	}

	total_size = 0;
	addr = 0;

	/*
	 * There are 2 cases to deal with. The program has a large NOBITS
	 * section and the relocations can fit entirely within occupied memory
	 * region for the program. The other is that the relocations increase
	 * the memory footprint of the program if it was loaded directly into
	 * the region it would run. The rmdoule header is a fixed cost that
	 * is considered a part of the program.
	 */
	total_size += buffer_size(&rmod_header);
	if (buffer_size(&relocs) + ctx->phdr->p_filesz > ctx->phdr->p_memsz) {
		total_size += buffer_size(&relocs);
		total_size += ctx->phdr->p_filesz;
	} else {
		total_size += ctx->phdr->p_memsz;
	}

	ret = add_section(ew, &rmod_header, ".header", addr,
	                  buffer_size(&rmod_header));
	if (ret < 0)
		goto out;
	addr += buffer_size(&rmod_header);

	ret = add_section(ew, &program, ".program", addr, ctx->phdr->p_filesz);
	if (ret < 0)
		goto out;
	addr += ctx->phdr->p_filesz;

	if (ctx->nrelocs) {
		ret = add_section(ew, &relocs, ".relocs", addr,
				  buffer_size(&relocs));
		if (ret < 0)
			goto out;
		addr += buffer_size(&relocs);
	}

	if (total_size != addr) {
		ret = add_section(ew, NULL, ".empty", addr, total_size - addr);
		if (ret < 0)
			goto out;
	}

	/*
	 * Ensure last section has a memory usage that meets the required
	 * total size of the program in memory.
	 */

	ret = elf_writer_serialize(ew, out);
	if (ret < 0)
		ERROR("Failed to serialize ELF to buffer.\n");

out:
	buffer_delete(&rmod_data);
	elf_writer_destroy(ew);

	return ret;
}
Пример #9
0
    DEFINE_FUNC_5(webp_encode_argb, data_buffer_value, width_value, height_value, lossless_value, quality_factor_value) {
        int width = 0;
        int height = 0;
        float quality_factor = 100;
        int lossless = 1;
        int stride = 0;
        uint8_t* abgr = NULL;
        uint8_t* rgba = NULL;
        uint8_t* output = NULL;
        int output_size = 0;
        int pixels_size;
        int bytes_size;
        buffer data_buffer;

        if (val_is_int(width_value)) width = val_int(width_value);
        if (val_is_int(height_value)) height = val_int(height_value);
        if (val_is_bool(lossless_value)) lossless = val_bool(lossless_value);
        if (val_is_float(quality_factor_value)) quality_factor = val_float(quality_factor_value);

        stride = width * 4;
        pixels_size = width * height;
        bytes_size = pixels_size * 4;

        if (!val_is_buffer(data_buffer_value)) {
            val_throw(alloc_string("webp_encode_argb: Expected to be a buffer"));
            return alloc_null();
        }

        data_buffer = val_to_buffer(data_buffer_value);

        if (bytes_size != buffer_size(data_buffer)) {
            val_throw(alloc_string("webp_encode_argb: Invalid buffer size"));
            return alloc_null();
        }

        //if ()

        abgr = (uint8_t *)buffer_data(data_buffer);
        rgba = (uint8_t *)malloc(bytes_size);

        uint8_t* _abgr = abgr;
        uint8_t* _rgba = rgba;
        int _pixels_size = pixels_size;

        while (_pixels_size-- > 0) {
            //_rgba[0] = _abgr[3];
            _rgba[0] = _abgr[1];
            _rgba[1] = _abgr[2];
            _rgba[2] = _abgr[3];
            _rgba[3] = _abgr[0];
            _abgr += 4;
            _rgba += 4;
        }

        if (lossless) {
            output_size = WebPEncodeLosslessRGBA(
                              rgba,
                              //abgr,
                              width, height, stride,
                              &output
                          );
        } else {
            output_size = WebPEncodeRGBA(
                              rgba,
                              //abgr,
                              width, height, stride,
                              quality_factor,
                              &output
                          );
        }

        printf("output_size: (%d, %d, %d) : %d\n", width, height, stride, output_size);

        buffer output_buffer = alloc_buffer_len(0);
        buffer_append_sub(output_buffer, (char *)output, output_size);
        buffer_set_size(output_buffer, output_size);

        if (output != NULL) free(output);
        if (rgba != NULL) free(rgba);

        return buffer_val(output_buffer);
    }
Пример #10
0
/*
 * Serialize the ELF file to the output buffer. Return < 0 on error,
 * 0 on success.
 */
int elf_writer_serialize(struct elf_writer *ew, struct buffer *out)
{
	Elf64_Half i;
	Elf64_Xword metadata_size;
	Elf64_Xword program_size;
	Elf64_Off shstroffset;
	size_t shstrlen;
	struct buffer metadata;
	struct buffer phdrs;
	struct buffer data;
	struct buffer *strtab;

	INFO("Writing %zu sections.\n", ew->num_secs);

	/* Determine size of sections to be written. */
	program_size = 0;
	/* Start with 1 byte for first byte of section header string table. */
	shstrlen = 1;
	for (i = 0; i < ew->num_secs; i++) {
		struct elf_writer_section *sec = &ew->sections[i];

		if (sec->shdr.sh_flags & SHF_ALLOC)
			ew->ehdr.e_phnum++;

		program_size += buffer_size(&sec->content);

		/* Keep track of the length sections' names. */
		if (sec->name != NULL) {
			sec->shdr.sh_name = shstrlen;
			shstrlen += strlen(sec->name) + 1;
		}
	}
	ew->ehdr.e_shnum = ew->num_secs;
	metadata_size = 0;
	metadata_size += ew->ehdr.e_ehsize;
	metadata_size += ew->ehdr.e_shnum * ew->ehdr.e_shentsize;
	metadata_size += ew->ehdr.e_phnum * ew->ehdr.e_phentsize;
	shstroffset = metadata_size;
	/* Align up section header string size and metadata size to 4KiB */
	metadata_size = ALIGN(metadata_size + shstrlen, 4096);

	if (buffer_create(out, metadata_size + program_size, "elfout")) {
		ERROR("Could not create output buffer for ELF.\n");
		return -1;
	}

	INFO("Created %zu output buffer for ELF file.\n", buffer_size(out));

	/*
	 * Write out ELF header. Section headers come right after ELF header
	 * followed by the program headers. Buffers need to be created first
	 * to do the writing.
	 */
	ew->ehdr.e_shoff = ew->ehdr.e_ehsize;
	ew->ehdr.e_phoff = ew->ehdr.e_shoff +
	                   ew->ehdr.e_shnum * ew->ehdr.e_shentsize;

	buffer_splice(&metadata, out, 0, metadata_size);
	buffer_splice(&phdrs, out, ew->ehdr.e_phoff,
	              ew->ehdr.e_phnum * ew->ehdr.e_phentsize);
	buffer_splice(&data, out, metadata_size, program_size);
	/* Set up the section header string table contents. */
	strtab = &ew->shstrtab->content;
	buffer_splice(strtab, out, shstroffset, shstrlen);
	ew->shstrtab->shdr.sh_size = shstrlen;

	/* Reset current locations. */
	buffer_set_size(&metadata, 0);
	buffer_set_size(&data, 0);
	buffer_set_size(&phdrs, 0);
	buffer_set_size(strtab, 0);

	/* ELF Header */
	ehdr_write(ew, &metadata);

	/* Write out section headers, section strings, section content, and
	 * program headers. */
	ew->xdr->put8(strtab, 0);
	for (i = 0; i < ew->num_secs; i++) {
		Elf64_Phdr phdr;
		struct elf_writer_section *sec = &ew->sections[i];

		/* Update section offsets. Be sure to not update SHT_NULL. */
		if (sec == ew->shstrtab)
			sec->shdr.sh_offset = shstroffset;
		else if (i != 0)
			sec->shdr.sh_offset = buffer_size(&data) +
			                      metadata_size;
		shdr_write(ew, i, &metadata);

		/* Add section name to string table. */
		if (sec->name != NULL)
			bputs(strtab, sec->name, strlen(sec->name) + 1);

		if (!(sec->shdr.sh_flags & SHF_ALLOC))
			continue;

		bputs(&data, buffer_get(&sec->content),
		      buffer_size(&sec->content));

		phdr.p_type = PT_LOAD;
		phdr.p_offset = sec->shdr.sh_offset;
		phdr.p_vaddr = sec->shdr.sh_addr;
		phdr.p_paddr = sec->shdr.sh_addr;
		phdr.p_filesz = buffer_size(&sec->content);
		phdr.p_memsz = sec->shdr.sh_size;
		phdr.p_flags = 0;
		if (sec->shdr.sh_flags & SHF_EXECINSTR)
			phdr.p_flags |= PF_X | PF_R;
		if (sec->shdr.sh_flags & SHF_WRITE)
			phdr.p_flags |= PF_W;
		phdr.p_align = sec->shdr.sh_addralign;
		phdr_write(ew, &phdrs, &phdr);
	}

	return 0;
}
Пример #11
0
/* video_init */
static VideoPhonePlugin * _video_init(PhonePluginHelper * helper)
{
	VideoPhonePlugin * video;
	struct v4l2_capability cap;
	struct v4l2_cropcap cropcap;
	struct v4l2_crop crop;
	struct v4l2_format format;

	if((video = object_new(sizeof(*video))) == NULL)
		return NULL;
	video->helper = helper;
	/* FIXME let this be configurable */
	video->fd = open("/dev/video0", O_RDWR);
	video->buffer = buffer_new(0, NULL);
	video->source = 0;
	video->window = NULL;
	/* check for errors */
	if(video->buffer == NULL
			|| video->fd < 0
			|| _video_ioctl(video, VIDIOC_QUERYCAP, &cap) == -1
			|| (cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) == 0
			/* FIXME also implement mmap() and streaming */
			|| (cap.capabilities & V4L2_CAP_READWRITE) == 0)
	{
		helper->error(helper->phone,
				"Could not open the video capture device", 1);
		_video_destroy(video);
		return NULL;
	}
	/* reset cropping */
	memset(&cropcap, 0, sizeof(cropcap));
	cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
	if(_video_ioctl(video, VIDIOC_CROPCAP, &cropcap) == 0)
	{
		/* reset to default */
		crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
		crop.c = cropcap.defrect;
		if(_video_ioctl(video, VIDIOC_S_CROP, &crop) == -1
				&& errno == EINVAL)
			helper->error(helper->phone, "Cropping not supported",
					0);
	}
	/* obtain the current format */
	if(_video_ioctl(video, VIDIOC_G_FMT, &format) == -1
			|| buffer_set_size(video->buffer,
				format.fmt.pix.sizeimage) != 0)
	{
		_video_destroy(video);
		return NULL;
	}
	/* create the window */
	video->window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
	gtk_window_set_resizable(GTK_WINDOW(video->window), FALSE);
	gtk_window_set_title(GTK_WINDOW(video->window), "Phone - Video");
	g_signal_connect_swapped(video->window, "delete-event", G_CALLBACK(
				_video_on_closex), video);
	video->area = gtk_drawing_area_new();
	gtk_widget_set_size_request(video->area, format.fmt.pix.width,
			format.fmt.pix.height);
	gtk_container_add(GTK_CONTAINER(video->window), video->area);
	gtk_widget_show_all(video->window);
	if(_video_on_refresh(video) == TRUE)
		video->source = g_timeout_add(1000, _video_on_refresh, video);
	return video;
}
Пример #12
0
int parse_elf_to_xip_stage(const struct buffer *input, struct buffer *output,
				uint32_t *location, const char *ignore_section)
{
	struct xip_context xipctx;
	struct rmod_context *rmodctx;
	struct reloc_filter filter;
	struct parsed_elf *pelf;
	size_t output_sz;
	uint32_t adjustment;
	struct buffer binput;
	struct buffer boutput;
	Elf64_Xword i;
	int ret = -1;

	xipctx.ignored_section_idx = 0;
	rmodctx = &xipctx.rmodctx;
	pelf = &rmodctx->pelf;

	if (rmodule_init(rmodctx, input))
		return -1;

	/* Only support x86 XIP currently. */
	if (rmodctx->pelf.ehdr.e_machine != EM_386) {
		ERROR("Only support XIP stages for x86\n");
		goto out;
	}

	xipctx.ignored_section =
		find_ignored_section_header(pelf, ignore_section);

	if (xipctx.ignored_section != NULL)
		xipctx.ignored_section_idx =
			xipctx.ignored_section - pelf->shdr;

	filter.filter = rmod_filter;
	filter.context = &xipctx;

	if (rmodule_collect_relocations(rmodctx, &filter))
		goto out;

	output_sz = sizeof(struct cbfs_stage) + pelf->phdr->p_filesz;
	if (buffer_create(output, output_sz, input->name) != 0) {
		ERROR("Unable to allocate memory: %m\n");
		goto out;
	}
	buffer_clone(&boutput, output);
	memset(buffer_get(&boutput), 0, output_sz);
	buffer_set_size(&boutput, 0);

	/* Single loadable segment. The entire segment moves to final
	 * location from based on virtual address of loadable segment. */
	adjustment = *location - pelf->phdr->p_vaddr;
	DEBUG("Relocation adjustment: %08x\n", adjustment);

	fill_cbfs_stage(&boutput, CBFS_COMPRESS_NONE,
			(uint32_t)pelf->ehdr.e_entry + adjustment,
			(uint32_t)pelf->phdr->p_vaddr + adjustment,
			pelf->phdr->p_filesz, pelf->phdr->p_memsz);
	/* Need an adjustable buffer. */
	buffer_clone(&binput, input);
	buffer_seek(&binput, pelf->phdr->p_offset);
	bputs(&boutput, buffer_get(&binput), pelf->phdr->p_filesz);

	buffer_clone(&boutput, output);
	buffer_seek(&boutput, sizeof(struct cbfs_stage));

	/* Make adjustments to all the relocations within the program. */
	for (i = 0; i < rmodctx->nrelocs; i++) {
		size_t reloc_offset;
		uint32_t val;
		struct buffer in, out;

		/* The relocations represent in-program addresses of the
		 * linked program. Obtain the offset into the program to do
		 * the adjustment. */
		reloc_offset = rmodctx->emitted_relocs[i] - pelf->phdr->p_vaddr;

		buffer_clone(&out, &boutput);
		buffer_seek(&out, reloc_offset);
		buffer_clone(&in, &out);
		/* Appease around xdr semantics: xdr decrements buffer
		 * size when get()ing and appends to size when put()ing. */
		buffer_set_size(&out, 0);

		val = xdr_le.get32(&in);
		DEBUG("reloc %zx %08x -> %08x\n", reloc_offset, val,
			val + adjustment);
		xdr_le.put32(&out, val + adjustment);
	}

	/* Need to back up the location to include cbfs stage metadata. */
	*location -= sizeof(struct cbfs_stage);
	ret = 0;

out:
	rmodule_cleanup(rmodctx);
	return ret;
}