[Skiboot] [PATCH 2/2] libflash/file: add file abstraction for libflash

Daniel Axtens dja at axtens.net
Thu Apr 2 08:48:35 AEDT 2015


Hi Cyril,

Looks good. Stewart, I assume you're dealing with the appropriate
copyright boilerplate at the top of each new file?

Reviewed-by: Daniel Axtens <dja at axtens.net>

Regards,
Daniel

On Wed, 2015-04-01 at 16:51 +1100, Cyril Bur wrote:
> The functionality provided by libflash and libffs are useful and it would be
> good to use them on dumps of flash or even access flash from userland through
> MTD devices which are presented as files.
> 
> Signed-off-by: Cyril Bur <cyril.bur at au1.ibm.com>
> ---
>  libflash/file_flash.c    | 223 +++++++++++++++++++++++++++++++++++++++++++++++
>  libflash/file_flash.h    |  11 +++
>  libflash/libflash-priv.h |   2 +
>  libflash/libflash.c      |   1 +
>  4 files changed, 237 insertions(+)
>  create mode 100644 libflash/file_flash.c
>  create mode 100644 libflash/file_flash.h
> 
> diff --git a/libflash/file_flash.c b/libflash/file_flash.c
> new file mode 100644
> index 0000000..0fe46c4
> --- /dev/null
> +++ b/libflash/file_flash.c
> @@ -0,0 +1,223 @@
> +#include <unistd.h>
> +#include <sys/types.h>
> +#include <sys/stat.h>
> +#include <stdbool.h>
> +#include <stdlib.h>
> +#include <sys/ioctl.h>
> +#include <sys/mman.h>
> +#include <string.h>
> +
> +#include <mtd/mtd-abi.h>
> +
> +#include "file_flash.h"
> +
> +struct file_flash_priv {
> +	int fd;
> +};
> +
> +/*
> + * Unfortunately not all file descriptors are created equal...
> + * Here we check to see if the file descriptor is to an MTD device, in which
> + * case we have to get the size of it differently.
> + */
> +int file_setup(struct spi_flash_ctrl *ctrl, uint32_t *tsize)
> +{
> +	struct mtd_info_user mtd_info;
> +	struct file_flash_priv *file_flash_data;
> +	struct stat sbuf;
> +
> +	if (!ctrl || !ctrl->priv)
> +		return -1;
> +
> +	file_flash_data = (struct file_flash_priv *)ctrl->priv;
> +
> +	if (fstat(file_flash_data->fd, &sbuf) == -1)
> +		return -1;
> +
> +	if (S_ISCHR(sbuf.st_mode)) {
> +		if (ioctl(file_flash_data->fd, MEMGETINFO, &mtd_info) == -1)
> +			return -1;
> +
> +		ctrl->finfo->size = mtd_info.size;
> +
> +	} else if (S_ISREG(sbuf.st_mode)) {
> +		ctrl->finfo->size = sbuf.st_size;
> +
> +	} else {
> +		/* Not going to be able to work with anything else */
> +		return -1;
> +	}
> +
> +	if (tsize)
> +		*tsize = ctrl->finfo->size;
> +
> +	return 0;
> +}
> +
> +int file_set4b(struct spi_flash_ctrl *ctrl, bool enable)
> +{
> +	/* Always report success no matter what, this isn't relevent for files */
> +	return 0;
> +}
> +
> +int file_chipid(struct spi_flash_ctrl *ctrl, uint8_t *id_buf,
> +		uint32_t *id_size)
> +{
> +	if (!ctrl || !ctrl->priv || !id_size || *id_size < 3)
> +		return -1;
> +
> +	id_buf[0] = 'M';
> +	id_buf[1] = 'T';
> +	id_buf[2] = 'D';
> +
> +	*id_size = 3;
> +	return 0;
> +}
> +
> +int file_read(struct spi_flash_ctrl *ctrl, uint32_t addr, void *buf,
> +		uint32_t size)
> +{
> +	int rc;
> +	struct file_flash_priv *file_flash_data;
> +
> +	if (!ctrl || !ctrl->priv)
> +		return -1;
> +
> +	file_flash_data = (struct file_flash_priv *)ctrl->priv;
> +
> +	rc = lseek(file_flash_data->fd, addr, SEEK_SET);
> +	if ((off_t )rc == (off_t )-1)
> +		return -1;
> +
> +	rc = read(file_flash_data->fd, buf, size);
> +	if (rc == -1)
> +		return -1;
> +	/* TODO Perhaps deal with short reads */
> +
> +	return 0;
> +}
> +
> +int file_write(struct spi_flash_ctrl *ctrl, uint32_t addr,
> +		const void *buf, uint32_t size)
> +{
> +	size_t rc;
> +	struct file_flash_priv *file_flash_data;
> +
> +	if (!ctrl || !ctrl->priv)
> +		return -1;
> +
> +	file_flash_data = (struct file_flash_priv *)ctrl->priv;
> +
> +	rc = lseek(file_flash_data->fd, addr, SEEK_SET);
> +	if ((off_t )rc == (off_t )-1)
> +		return -1;
> +
> +	rc = write(file_flash_data->fd, buf, size);
> +	if (rc != size)
> +		return -1;
> +	/* TODO Perhaps deal with short writes */
> +
> +	return 0;
> +}
> +
> +int file_erase(struct spi_flash_ctrl *ctrl, uint32_t addr,
> +		uint32_t size)
> +{
> +	struct stat sbuf;
> +	struct file_flash_priv *file_flash_data;
> +	uint32_t esize;
> +
> +	if (!ctrl || !ctrl->priv)
> +		return -1;
> +
> +	/*
> +	 * Input params addr = 0 and size = 0xffffffff mean libflash is telling us
> +	 * to erase the entire thing.
> +	 */
> +	file_flash_data = (struct file_flash_priv *)ctrl->priv;
> +
> +	esize = (size == 0xffffffff && addr == 0) ? ctrl->finfo->size : size;
> +	if (esize > ctrl->finfo->size)
> +		return -1;
> +
> +	if (fstat(file_flash_data->fd, &sbuf) == -1)
> +		return -1;
> +
> +	/*
> +	 * If we're dealing with an MTD device then its possible that there is a
> +	 * real flash device somewhere (as opposed to a regular file where the
> +	 * assumption is that there is not).
> +	 * In that case lets try to represerve that idea and use the erase ioctl.
> +	 */
> +	if (S_ISCHR(sbuf.st_mode)) {
> +		struct erase_info_user erase_info = {
> +			.start = addr,
> +			.length = esize
> +		};
> +
> +		if (ioctl(file_flash_data->fd, MEMERASE, erase_info) == -1)
> +			return -1;
> +
> +	} else if (S_ISREG(sbuf.st_mode)) {
> +		/* Regular file, erase is just write zeros */
> +		char *section;
> +
> +		section = mmap(NULL, sbuf.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, file_flash_data->fd, 0);
> +		if (section == (void *)-1)
> +			return -1;
> +		bzero(section + addr, esize);
> +		if (munmap(section, sbuf.st_size) == -1)
> +			return -1;
> +
> +	} else {
> +		return -1;
> +	}
> +
> +	return 0;
> +}
> +
> +/* To be called by tools wanting to use the libflash/libffs APIs */
> +struct spi_flash_ctrl *build_flash_ctrl(int fd)
> +{
> +	struct spi_flash_ctrl *ctrl;
> +	struct file_flash_priv *data;
> +
> +	ctrl = calloc(1, sizeof(struct spi_flash_ctrl));
> +	if (!ctrl)
> +		return NULL;
> +
> +	data = calloc(1, sizeof(struct file_flash_priv));
> +	if (!data) {
> +		free(ctrl);
> +		return NULL;
> +	}
> +
> +	data->fd = fd;
> +
> +	/*
> +	 * Don't implement the low level interfaces because we aren't flash. This
> +	 * will also force libflash to only call us with the high level interface.
> +	 */
> +	ctrl->cmd_rd = NULL;
> +	ctrl->cmd_wr = NULL;
> +
> +	/*
> +	 * Do implement everything else.
> +	 */
> +	ctrl->erase = &file_erase;
> +	ctrl->write = &file_write;
> +	ctrl->read = &file_read;
> +	ctrl->chip_id = &file_chipid;
> +	ctrl->set_4b = &file_set4b;
> +	ctrl->setup = &file_setup;
> +
> +	ctrl->priv = data;
> +
> +	return ctrl;
> +}
> +
> +void free_flash_ctrl(struct spi_flash_ctrl *flash_ctrl)
> +{
> +	free(flash_ctrl->priv);
> +	free(flash_ctrl);
> +}
> diff --git a/libflash/file_flash.h b/libflash/file_flash.h
> new file mode 100644
> index 0000000..dc6b5d7
> --- /dev/null
> +++ b/libflash/file_flash.h
> @@ -0,0 +1,11 @@
> +#ifndef __FILE_FLASH_H
> +#define __FILE_FLASH_H
> +
> +#include <libflash/libflash.h>
> +#include <libflash/libflash-priv.h>
> +
> +struct spi_flash_ctrl *build_flash_ctrl(int fd);
> +
> +void free_flash_ctrl(struct spi_flash_ctrl *flash_ctrl);
> +
> +#endif /* __FILE_FLASH_H */
> diff --git a/libflash/libflash-priv.h b/libflash/libflash-priv.h
> index ba6da66..e59d829 100644
> --- a/libflash/libflash-priv.h
> +++ b/libflash/libflash-priv.h
> @@ -223,6 +223,8 @@ struct spi_flash_ctrl {
>  	 * been probed
>  	 */
>  	struct flash_info *finfo;
> +
> +	void *priv;
>  };
>  
>  extern int fl_wren(struct spi_flash_ctrl *ct);
> diff --git a/libflash/libflash.c b/libflash/libflash.c
> index bb6f097..e43be4f 100644
> --- a/libflash/libflash.c
> +++ b/libflash/libflash.c
> @@ -32,6 +32,7 @@ static const struct flash_info flash_info[] = {
>  	{ 0x20ba20, 0x04000000, FL_ERASE_4K  | FL_ERASE_64K | FL_CAN_4B |
>                                  FL_ERASE_BULK | FL_MICRON_BUGS,
>                                                            "Micron N25Qx512Ax"   },
> +	{ 0x4d5444, 0x02000000, FL_ERASE_ALL | FL_CAN_4B, "File Abstraction"},
>  	{ 0x55aa55, 0x00100000, FL_ERASE_ALL | FL_CAN_4B, "TEST_FLASH" },
>  	{ 0xaa55aa, 0x02000000, FL_ERASE_ALL | FL_CAN_4B, "EMULATED_FLASH"},
>  };

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 860 bytes
Desc: This is a digitally signed message part
URL: <http://lists.ozlabs.org/pipermail/skiboot/attachments/20150402/4da87ae8/attachment-0001.sig>


More information about the Skiboot mailing list