Nico Huber has uploaded this change for review.

View Change

[WIP] Add data source/sink abstraction `flashrom_data`

A first sketch. API will change when I see how it works out.

Change-Id: Ie550914eca2cffb4c14cfdd76289334a2f0636b9
Signed-off-by: Nico Huber <nico.h@gmx.de>
---
M Makefile
M flash.h
A flashrom_data.c
A flashrom_data_file.c
M libflashrom.h
A libflashrom_file.h
6 files changed, 373 insertions(+), 1 deletion(-)

git pull ssh://review.coreboot.org:29418/flashrom refs/changes/72/33372/1
diff --git a/Makefile b/Makefile
index e08a3f6..744344a 100644
--- a/Makefile
+++ b/Makefile
@@ -547,7 +547,10 @@
###############################################################################
# Library code.

-LIB_OBJS = libflashrom.o layout.o flashrom.o udelay.o programmer.o helpers.o ich_descriptors.o fmap.o
+LIB_OBJS = libflashrom.o flashrom_data.o layout.o flashrom.o udelay.o programmer.o helpers.o ich_descriptors.o fmap.o
+ifneq ($(TARGET_OS), libpayload)
+LIB_OBJS += flashrom_data_file.o
+endif

###############################################################################
# Frontend related stuff.
diff --git a/flash.h b/flash.h
index 911214c..af01479 100644
--- a/flash.h
+++ b/flash.h
@@ -55,6 +55,8 @@

#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))

+#define container_of(ptr, type, member) ((type *)((char *)ptr - offsetof(type, member)))
+
enum chipbustype {
BUS_NONE = 0,
BUS_PARALLEL = 1 << 0,
@@ -267,6 +269,10 @@
bool in_4ba_mode;
};

+static inline size_t total_size(const struct flashrom_flashctx *flash) {
+ return flash ? flash->chip ? flash->chip->total_size * 1024 : 0 : 0;
+};
+
/* Timing used in probe routines. ZERO is -2 to differentiate between an unset
* field and zero delay.
*
diff --git a/flashrom_data.c b/flashrom_data.c
new file mode 100644
index 0000000..5e541a9
--- /dev/null
+++ b/flashrom_data.c
@@ -0,0 +1,220 @@
+/*
+ * This file is part of the flashrom project.
+ *
+ * Copyright (C) 2019 Nico Huber <nico.h@gmx.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "flash.h"
+#include "libflashrom.h"
+
+/**
+ * @defgroup flashrom-data Data sources/sinks
+ * @{
+ */
+
+struct flash_data {
+ struct flashrom_data data;
+ struct flashrom_flashctx *flash;
+};
+#define FLASH_DATA(d) container_of(d, struct flash_data, data)
+
+static ssize_t flash_readat(
+ void *const buf, const struct flashrom_data *const data,
+ const off_t offset, const size_t count)
+{
+ const struct flash_data *const fdata = FLASH_DATA(data);
+
+ if (!data || !fdata->flash || !fdata->flash->chip || !fdata->flash->chip->read)
+ return -1;
+
+ return fdata->flash->chip->read(fdata->flash, buf, offset, count);
+}
+
+static void flash_release(struct flashrom_data *const data)
+{
+ free(FLASH_DATA(data));
+}
+
+int flashrom_data_from_flash(
+ struct flashrom_data **const data, struct flashrom_flashctx *const flash)
+{
+ struct flash_data *const fdata = malloc(sizeof(*fdata));
+
+ if (!fdata)
+ return -1;
+
+ memset(fdata, 0x00, sizeof(*fdata));
+ fdata->flash = flash;
+ fdata->data.size = total_size(flash);
+ fdata->data.readat = flash_readat;
+ fdata->data.release = flash_release;
+
+ *data = &fdata->data;
+ return 0;
+}
+
+struct buffer_data {
+ struct flashrom_data data;
+ void *buf;
+};
+#define BUFFER_DATA(d) container_of(d, struct buffer_data, data)
+
+static ssize_t buffer_readat(
+ void *const buf, const struct flashrom_data *const data,
+ const off_t offset, const size_t count)
+{
+ const struct buffer_data *const bdata = BUFFER_DATA(data);
+
+ if (!data || !bdata->buf || offset + count > data->size)
+ return -1;
+
+ memcpy(buf, (char *)bdata->buf + offset, count);
+ return count;
+}
+
+static ssize_t buffer_writeat(
+ const struct flashrom_data *const data, const off_t offset,
+ const void *const buf, const size_t count)
+{
+ const struct buffer_data *const bdata = BUFFER_DATA(data);
+
+ if (!data || !bdata->buf || offset + count > data->size)
+ return -1;
+
+ memcpy((char *)bdata->buf + offset, buf, count);
+ return count;
+}
+
+static void buffer_release(struct flashrom_data *const data)
+{
+ free(BUFFER_DATA(data));
+}
+
+int flashrom_data_from_buf(
+ struct flashrom_data **const data, void *const buf, const size_t size)
+{
+ struct buffer_data *const bdata = malloc(sizeof(*bdata));
+
+ if (!bdata)
+ return -1;
+
+ memset(bdata, 0x00, sizeof(*bdata));
+ bdata->buf = buf;
+ bdata->data.size = size;
+ bdata->data.readat = buffer_readat;
+ bdata->data.writeat = buffer_writeat;
+ bdata->data.release = buffer_release;
+
+ *data = &bdata->data;
+ return 0;
+}
+
+struct sub_data {
+ struct flashrom_data data;
+ const struct flashrom_data *parent;
+ off_t offset;
+};
+#define SUB_DATA(d) container_of(d, struct sub_data, data)
+
+static ssize_t sub_readat(
+ void *const buf, const struct flashrom_data *const data,
+ const off_t offset, const size_t count)
+{
+ const struct sub_data *const sdata = SUB_DATA(data);
+
+ if (!data || !sdata->parent || !sdata->parent->readat ||
+ offset + count > data->size)
+ return -1;
+
+ return sdata->parent->readat(buf, sdata->parent, sdata->offset + offset, count);
+}
+
+static ssize_t sub_writeat(
+ const struct flashrom_data *const data, const off_t offset,
+ const void *const buf, const size_t count)
+{
+ const struct sub_data *const sdata = SUB_DATA(data);
+
+ if (!data || !sdata->parent || !sdata->parent->writeat ||
+ offset + count > data->size)
+ return -1;
+
+ return sdata->parent->writeat(sdata->parent, sdata->offset + offset, buf, count);
+}
+
+static void sub_release(struct flashrom_data *const data)
+{
+ free(SUB_DATA(data));
+}
+
+int flashrom_data_subregion(
+ struct flashrom_data **const data,
+ const struct flashrom_data *const parent,
+ const off_t offset, const size_t size)
+{
+ if (!parent || offset + size > parent.size)
+ return -1;
+
+ struct sub_data *const sdata = malloc(sizeof(*sdata));
+
+ if (!sdata)
+ return -1;
+
+ memset(sdata, 0x00, sizeof(*sdata));
+ sdata->parent = parent;
+ sdata->offset = offset;
+ sdata->data.size = size;
+ sdata->data.readat = parent->readat ? sub_readat : NULL;
+ sdata->data.writeat = parent->writeat ? sub_writeat : NULL;
+ sdata->data.release = sub_release;
+
+ *data = &sdata->data;
+ return 0;
+}
+
+ssize_t flashrom_data_copy(
+ const struct flashrom_data *const dst,
+ const struct flashrom_data *const src)
+{
+ ssize_t ret = -1;
+
+ if (!dst || !dst->writeat || !src || !src->readat)
+ return ret;
+ if (dst->size != src->size)
+ return ret;
+
+ void *const buf = malloc(dst->size);
+ if (!buf)
+ return ret;
+
+ if (src->readat(buf, src, 0, dst->size) != dst->size)
+ goto _free_ret;
+
+ ret = dst->writeat(dst, 0, buf, dst->size);
+
+_free_ret:
+ free(buf);
+ return ret;
+}
+
+void flashrom_data_release(struct flashrom_data *const data)
+{
+ if (data->release)
+ data->release(data);
+}
+
+/** @} */ /* end flashrom-data */
diff --git a/flashrom_data_file.c b/flashrom_data_file.c
new file mode 100644
index 0000000..d7e1c66
--- /dev/null
+++ b/flashrom_data_file.c
@@ -0,0 +1,95 @@
+/*
+ * This file is part of the flashrom project.
+ *
+ * Copyright (C) 2019 Nico Huber <nico.h@gmx.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "flash.h"
+#include "libflashrom.h"
+#include "libflashrom_file.h"
+
+/** @ingroup flashrom-data */
+
+struct file_data {
+ struct flashrom_data data;
+ FILE *file;
+};
+#define FILE_DATA(d) container_of(d, struct file_data, data)
+
+static ssize_t file_readat(
+ void *const buf, const struct flashrom_data *const data,
+ const off_t offset, const size_t count)
+{
+ const struct file_data *const fdata = FILE_DATA(data);
+
+ if (!data || !fdata->file)
+ return -1;
+
+ if (fseek(fdata->file, offset, SEEK_SET) != 0)
+ return -1;
+ if (fread(buf, count, 1, fdata->file) != 1)
+ return -1;
+
+ return count;
+}
+
+static ssize_t file_writeat(
+ const struct flashrom_data *const data, const off_t offset,
+ const void *const buf, const size_t count)
+{
+ const struct file_data *const fdata = FILE_DATA(data);
+
+ if (!data || !fdata->file)
+ return -1;
+
+ if (fseek(fdata->file, offset, SEEK_SET) != 0)
+ return -1;
+ if (fwrite(buf, count, 1, fdata->file) != 1)
+ return -1;
+
+ return count;
+}
+
+static void file_release(struct flashrom_data *const data)
+{
+ free(FILE_DATA(data));
+}
+
+int flashrom_data_from_file(struct flashrom_data **const data, FILE *const file)
+{
+ struct file_data *const fdata = malloc(sizeof(*fdata));
+
+ if (!fdata || !file)
+ return -1;
+
+ if (fseek(file, 0, SEEK_END) != 0)
+ return -1;
+
+ const long pos = ftell(file);
+ if (pos < 0 || pos > SIZE_MAX)
+ return -1;
+
+ memset(fdata, 0x00, sizeof(*fdata));
+ fdata->file = file;
+ fdata->data.size = (size_t)pos;
+ fdata->data.readat = file_readat;
+ fdata->data.writeat = file_writeat;
+ fdata->data.release = file_release;
+
+ *data = &fdata->data;
+ return 0;
+}
diff --git a/libflashrom.h b/libflashrom.h
index 38c95d2..01ecd3f 100644
--- a/libflashrom.h
+++ b/libflashrom.h
@@ -3,6 +3,7 @@
*
* Copyright (C) 2012 secunet Security Networks AG
* (Written by Nico Huber <nico.huber@secunet.com> for secunet)
+ * Copyright (C) 2019 Nico Huber <nico.h@gmx.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -47,6 +48,26 @@
int flashrom_flash_erase(struct flashrom_flashctx *);
void flashrom_flash_release(struct flashrom_flashctx *);

+/** @ingroup flashrom-data */
+/** Representation of a data source/sink (can be flash, a file, memory buffer, ...) */
+struct flashrom_data {
+ size_t size;
+
+ /* Offsets are relative to the `flashrom_data` instance, not the `buf`. */
+ ssize_t (*readat)(void *buf, const struct flashrom_data *, off_t offset, size_t count);
+ ssize_t (*writeat)(const struct flashrom_data *, off_t offset, const void *buf, size_t count);
+
+ void (*release)(struct flashrom_data *);
+};
+
+int flashrom_data_from_flash(struct flashrom_data **, struct flashrom_flashctx *);
+int flashrom_data_from_buf(struct flashrom_data **, void *, size_t);
+int flashrom_data_subregion(struct flashrom_data **, const struct flashrom_data *parent, off_t, size_t);
+
+ssize_t flashrom_data_copy(const struct flashrom_data *dst, const struct flashrom_data *src);
+
+void flashrom_data_release(struct flashrom_data *);
+
/** @ingroup flashrom-flash */
enum flashrom_flag {
FLASHROM_FLAG_FORCE,
diff --git a/libflashrom_file.h b/libflashrom_file.h
new file mode 100644
index 0000000..54de515
--- /dev/null
+++ b/libflashrom_file.h
@@ -0,0 +1,27 @@
+/*
+ * This file is part of the flashrom project.
+ *
+ * Copyright (C) 2019 Nico Huber <nico.h@gmx.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __LIBFLASHROM_FILE_H__
+#define __LIBFLASHROM_FILE_H__ 1
+
+#include <stdio.h>
+
+#include "libflashrom.h"
+
+/** @ingroup flashrom-data */
+int flashrom_data_from_file(struct flashrom_data **, FILE *);
+
+#endif /* !__LIBFLASHROM_FILE_H__ */

To view, visit change 33372. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-Project: flashrom
Gerrit-Branch: master
Gerrit-Change-Id: Ie550914eca2cffb4c14cfdd76289334a2f0636b9
Gerrit-Change-Number: 33372
Gerrit-PatchSet: 1
Gerrit-Owner: Nico Huber <nico.h@gmx.de>
Gerrit-MessageType: newchange