All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/5] mtd-utils: Add fastmap support to ubinize
@ 2018-05-14 11:25 Richard Weinberger
  2018-05-14 11:25 ` [PATCH 1/5] Sync ubi-media.h with Linux Richard Weinberger
                   ` (4 more replies)
  0 siblings, 5 replies; 8+ messages in thread
From: Richard Weinberger @ 2018-05-14 11:25 UTC (permalink / raw)
  To: linux-mtd; +Cc: linux-kernel, goliath, Richard Weinberger

This is the userspace side of my preseeded fastmap series.
ubinize can now created images with a preloaded fastmap on it.

Richard Weinberger (5):
  Sync ubi-media.h with Linux
  ubinize: Don't stat image file twice
  libubigen: Carry image path and size in volume info
  libubigen: Maintain a eraseblock association table
  ubinize: Add fastmap support

 include/libubigen.h     |  25 ++++-
 include/mtd/ubi-media.h | 158 +++++++++++++++++++++++++++++--
 lib/libubigen.c         | 241 ++++++++++++++++++++++++++++++++++++++++++++----
 ubi-utils/ubiformat.c   |   6 +-
 ubi-utils/ubinize.c     | 120 ++++++++++++++++--------
 5 files changed, 477 insertions(+), 73 deletions(-)

-- 
2.13.6

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH 1/5] Sync ubi-media.h with Linux
  2018-05-14 11:25 [PATCH 0/5] mtd-utils: Add fastmap support to ubinize Richard Weinberger
@ 2018-05-14 11:25 ` Richard Weinberger
  2018-05-14 11:25 ` [PATCH 2/5] ubinize: Don't stat image file twice Richard Weinberger
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 8+ messages in thread
From: Richard Weinberger @ 2018-05-14 11:25 UTC (permalink / raw)
  To: linux-mtd; +Cc: linux-kernel, goliath, Richard Weinberger

...to get UBI Fastmap on-fast layout.

Signed-off-by: Richard Weinberger <richard@nod.at>
---
 include/mtd/ubi-media.h | 158 ++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 152 insertions(+), 6 deletions(-)

diff --git a/include/mtd/ubi-media.h b/include/mtd/ubi-media.h
index 08bec3ed96f0..a2c471210202 100644
--- a/include/mtd/ubi-media.h
+++ b/include/mtd/ubi-media.h
@@ -149,10 +149,10 @@ enum {
  * The @image_seq field is used to validate a UBI image that has been prepared
  * for a UBI device. The @image_seq value can be any value, but it must be the
  * same on all eraseblocks. UBI will ensure that all new erase counter headers
- * also contain this value, and will check the value when scanning at start-up.
+ * also contain this value, and will check the value when attaching the flash.
  * One way to make use of @image_seq is to increase its value by one every time
  * an image is flashed over an existing image, then, if the flashing does not
- * complete, UBI will detect the error when scanning.
+ * complete, UBI will detect the error when attaching the media.
  */
 struct ubi_ec_hdr {
 	__be32  magic;
@@ -229,7 +229,7 @@ struct ubi_ec_hdr {
  * copy. UBI also calculates data CRC when the data is moved and stores it at
  * the @data_crc field of the copy (P1). So when UBI needs to pick one physical
  * eraseblock of two (P or P1), the @copy_flag of the newer one (P1) is
- * examined. If it is cleared, the situation* is simple and the newer one is
+ * examined. If it is cleared, the situation is simple and the newer one is
  * picked. If it is set, the data CRC of the copy (P1) is examined. If the CRC
  * checksum is correct, this physical eraseblock is selected (P1). Otherwise
  * the older one (P) is selected.
@@ -283,7 +283,7 @@ struct ubi_vid_hdr {
 	__u8    compat;
 	__be32  vol_id;
 	__be32  lnum;
-	__be32  leb_ver;
+	__u8    padding1[4];
 	__be32  data_size;
 	__be32  used_ebs;
 	__be32  data_pad;
@@ -298,8 +298,8 @@ struct ubi_vid_hdr {
 #define UBI_INT_VOL_COUNT 1
 
 /*
- * Starting ID of internal volumes. There is reserved room for 4096 internal
- * volumes.
+ * Starting ID of internal volumes: 0x7fffefff.
+ * There is reserved room for 4096 internal volumes.
  */
 #define UBI_INTERNAL_VOL_START (0x7FFFFFFF - 4096)
 
@@ -375,4 +375,150 @@ struct ubi_vtbl_record {
 	__be32  crc;
 } __attribute__ ((packed));
 
+/* UBI fastmap on-flash data structures */
+
+#define UBI_FM_SB_VOLUME_ID	(UBI_LAYOUT_VOLUME_ID + 1)
+#define UBI_FM_DATA_VOLUME_ID	(UBI_LAYOUT_VOLUME_ID + 2)
+
+/* fastmap on-flash data structure format version */
+#define UBI_FM_FMT_VERSION		2
+
+/* this implementation writes always version 1 */
+#define UBI_FM_FMT_WRITE_VERSION	1
+
+#define UBI_FM_SB_MAGIC		0x7B11D69F
+#define UBI_FM_HDR_MAGIC	0xD4B82EF7
+#define UBI_FM_VHDR_MAGIC	0xFA370ED1
+#define UBI_FM_POOL_MAGIC	0x67AF4D08
+#define UBI_FM_EBA_MAGIC	0xf0c040a8
+
+/* A fastmap super block can be located between PEB 0 and
+ * UBI_FM_MAX_START */
+#define UBI_FM_MAX_START	64
+
+/* A fastmap can use up to UBI_FM_MAX_BLOCKS PEBs */
+#define UBI_FM_MAX_BLOCKS	32
+
+/* 5% of the total number of PEBs have to be scanned while attaching
+ * from a fastmap.
+ * But the size of this pool is limited to be between UBI_FM_MIN_POOL_SIZE and
+ * UBI_FM_MAX_POOL_SIZE */
+#define UBI_FM_MIN_POOL_SIZE	8
+#define UBI_FM_MAX_POOL_SIZE	256
+
+enum {
+	UBI_FM_SB_PRESEEDED_FLG	= 0x1,
+};
+
+#define UBI_FM_SB_FLG_MASK (UBI_FM_SB_PRESEEDED_FLG)
+
+/**
+ * struct ubi_fm_sb - UBI fastmap super block
+ * @magic: fastmap super block magic number (%UBI_FM_SB_MAGIC)
+ * @version: format version of this fastmap
+ * @data_crc: CRC over the fastmap data
+ * @used_blocks: number of PEBs used by this fastmap
+ * @block_loc: an array containing the location of all PEBs of the fastmap
+ * @block_ec: the erase counter of each used PEB
+ * @sqnum: highest sequence number value at the time while taking the fastmap
+ * @flags: fastmap specific flags, only used with @version > 1, zero otherwise
+ *
+ */
+struct ubi_fm_sb {
+	__be32 magic;
+	__u8 version;
+	__u8 padding1[3];
+	__be32 data_crc;
+	__be32 used_blocks;
+	__be32 block_loc[UBI_FM_MAX_BLOCKS];
+	__be32 block_ec[UBI_FM_MAX_BLOCKS];
+	__be64 sqnum;
+	__be32 flags;
+	__u8 padding2[28];
+} __attribute__ ((packed));
+
+/**
+ * struct ubi_fm_hdr - header of the fastmap data set
+ * @magic: fastmap header magic number (%UBI_FM_HDR_MAGIC)
+ * @free_peb_count: number of free PEBs known by this fastmap
+ * @used_peb_count: number of used PEBs known by this fastmap
+ * @scrub_peb_count: number of to be scrubbed PEBs known by this fastmap
+ * @bad_peb_count: number of bad PEBs known by this fastmap
+ * @erase_peb_count: number of bad PEBs which have to be erased
+ * @vol_count: number of UBI volumes known by this fastmap
+ */
+struct ubi_fm_hdr {
+	__be32 magic;
+	__be32 free_peb_count;
+	__be32 used_peb_count;
+	__be32 scrub_peb_count;
+	__be32 bad_peb_count;
+	__be32 erase_peb_count;
+	__be32 vol_count;
+	__u8 padding[4];
+} __attribute__ ((packed));
+
+/* struct ubi_fm_hdr is followed by two struct ubi_fm_scan_pool */
+
+/**
+ * struct ubi_fm_scan_pool - Fastmap pool PEBs to be scanned while attaching
+ * @magic: pool magic numer (%UBI_FM_POOL_MAGIC)
+ * @size: current pool size
+ * @max_size: maximal pool size
+ * @pebs: an array containing the location of all PEBs in this pool
+ */
+struct ubi_fm_scan_pool {
+	__be32 magic;
+	__be16 size;
+	__be16 max_size;
+	__be32 pebs[UBI_FM_MAX_POOL_SIZE];
+	__be32 padding[4];
+} __attribute__ ((packed));
+
+/* ubi_fm_scan_pool is followed by nfree+nused struct ubi_fm_ec records */
+
+/**
+ * struct ubi_fm_ec - stores the erase counter of a PEB
+ * @pnum: PEB number
+ * @ec: ec of this PEB
+ */
+struct ubi_fm_ec {
+	__be32 pnum;
+	__be32 ec;
+} __attribute__ ((packed));
+
+/**
+ * struct ubi_fm_volhdr - Fastmap volume header
+ * it identifies the start of an eba table
+ * @magic: Fastmap volume header magic number (%UBI_FM_VHDR_MAGIC)
+ * @vol_id: volume id of the fastmapped volume
+ * @vol_type: type of the fastmapped volume
+ * @data_pad: data_pad value of the fastmapped volume
+ * @used_ebs: number of used LEBs within this volume
+ * @last_eb_bytes: number of bytes used in the last LEB
+ */
+struct ubi_fm_volhdr {
+	__be32 magic;
+	__be32 vol_id;
+	__u8 vol_type;
+	__u8 padding1[3];
+	__be32 data_pad;
+	__be32 used_ebs;
+	__be32 last_eb_bytes;
+	__u8 padding2[8];
+} __attribute__ ((packed));
+
+/* struct ubi_fm_volhdr is followed by one struct ubi_fm_eba records */
+
+/**
+ * struct ubi_fm_eba - denotes an association between a PEB and LEB
+ * @magic: EBA table magic number
+ * @reserved_pebs: number of table entries
+ * @pnum: PEB number of LEB (LEB is the index)
+ */
+struct ubi_fm_eba {
+	__be32 magic;
+	__be32 reserved_pebs;
+	__be32 pnum[0];
+} __attribute__ ((packed));
 #endif /* !__UBI_MEDIA_H__ */
-- 
2.13.6

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 2/5] ubinize: Don't stat image file twice
  2018-05-14 11:25 [PATCH 0/5] mtd-utils: Add fastmap support to ubinize Richard Weinberger
  2018-05-14 11:25 ` [PATCH 1/5] Sync ubi-media.h with Linux Richard Weinberger
@ 2018-05-14 11:25 ` Richard Weinberger
  2018-05-14 11:25 ` [PATCH 3/5] libubigen: Carry image path and size in volume info Richard Weinberger
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 8+ messages in thread
From: Richard Weinberger @ 2018-05-14 11:25 UTC (permalink / raw)
  To: linux-mtd; +Cc: linux-kernel, goliath, Richard Weinberger

Signed-off-by: Richard Weinberger <richard@nod.at>
---
 ubi-utils/ubinize.c | 7 +------
 1 file changed, 1 insertion(+), 6 deletions(-)

diff --git a/ubi-utils/ubinize.c b/ubi-utils/ubinize.c
index c85ff9b22c58..3390d0d95305 100644
--- a/ubi-utils/ubinize.c
+++ b/ubi-utils/ubinize.c
@@ -335,16 +335,11 @@ static int read_section(const struct ubigen_info *ui, const char *sname,
 				      sname, *img, (long long)st->st_size, vi->bytes);
 		verbose(args.verbose, "volume size: %lld bytes", vi->bytes);
 	} else {
-		struct stat st;
-
 		if (!*img)
 			return errmsg("neither image file (\"image=\") nor volume size "
 				      "(\"vol_size=\") specified in section \"%s\"", sname);
 
-		if (stat(*img, &st))
-			return sys_errmsg("cannot stat \"%s\"", *img);
-
-		vi->bytes = st.st_size;
+		vi->bytes = st->st_size;
 
 		if (vi->bytes == 0)
 			return errmsg("file \"%s\" referred from section \"%s\" is empty",
-- 
2.13.6

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 3/5] libubigen: Carry image path and size in volume info
  2018-05-14 11:25 [PATCH 0/5] mtd-utils: Add fastmap support to ubinize Richard Weinberger
  2018-05-14 11:25 ` [PATCH 1/5] Sync ubi-media.h with Linux Richard Weinberger
  2018-05-14 11:25 ` [PATCH 2/5] ubinize: Don't stat image file twice Richard Weinberger
@ 2018-05-14 11:25 ` Richard Weinberger
  2018-05-14 11:25 ` [PATCH 4/5] libubigen: Maintain a eraseblock association table Richard Weinberger
  2018-05-14 11:25 ` [PATCH 5/5] ubinize: Add fastmap support Richard Weinberger
  4 siblings, 0 replies; 8+ messages in thread
From: Richard Weinberger @ 2018-05-14 11:25 UTC (permalink / raw)
  To: linux-mtd; +Cc: linux-kernel, goliath, Richard Weinberger

...instead of passing them a extra parameters.

Signed-off-by: Richard Weinberger <richard@nod.at>
---
 include/libubigen.h |  7 +++++--
 lib/libubigen.c     |  3 ++-
 ubi-utils/ubinize.c | 41 ++++++++++++++++++++---------------------
 3 files changed, 27 insertions(+), 24 deletions(-)

diff --git a/include/libubigen.h b/include/libubigen.h
index c25ac20fbdc2..8084d0ecddb2 100644
--- a/include/libubigen.h
+++ b/include/libubigen.h
@@ -74,6 +74,8 @@ struct ubigen_info
  * @bytes: size of the volume contents in bytes (relevant for static volumes
  *         only)
  * @flags: volume flags (%UBI_VTBL_AUTORESIZE_FLG)
+ * @image_file: file to read volume contents from, can be NULL
+ * @image_file_len: length of %image_file in bytes
  */
 struct ubigen_vol_info
 {
@@ -88,6 +90,8 @@ struct ubigen_vol_info
 	int used_ebs;
 	long long bytes;
 	uint8_t flags;
+	const char *image_file;
+	size_t image_file_len;
 };
 
 /**
@@ -159,7 +163,6 @@ int ubigen_add_volume(const struct ubigen_info *ui,
  * @ui: libubigen information
  * @vi: volume information
  * @ec: erase counter value to put to EC headers
- * @bytes: volume size in bytes
  * @in: input file descriptor (has to be properly seeked)
  * @out: output file descriptor
  *
@@ -169,7 +172,7 @@ int ubigen_add_volume(const struct ubigen_info *ui,
  */
 int ubigen_write_volume(const struct ubigen_info *ui,
 			const struct ubigen_vol_info *vi, long long ec,
-			long long bytes, int in, int out);
+			int in, int out);
 
 /**
  * ubigen_write_layout_vol - write UBI layout volume
diff --git a/lib/libubigen.c b/lib/libubigen.c
index d2a949be90c2..900c984229fb 100644
--- a/lib/libubigen.c
+++ b/lib/libubigen.c
@@ -170,9 +170,10 @@ void ubigen_init_vid_hdr(const struct ubigen_info *ui,
 
 int ubigen_write_volume(const struct ubigen_info *ui,
 			const struct ubigen_vol_info *vi, long long ec,
-			long long bytes, int in, int out)
+			int in, int out)
 {
 	int len = vi->usable_leb_size, rd, lnum = 0;
+	long long bytes = vi->image_file_len;
 	char *inbuf, *outbuf;
 
 	if (vi->id >= ui->max_volumes) {
diff --git a/ubi-utils/ubinize.c b/ubi-utils/ubinize.c
index 3390d0d95305..bffb66ebcbd9 100644
--- a/ubi-utils/ubinize.c
+++ b/ubi-utils/ubinize.c
@@ -241,13 +241,13 @@ static int parse_opt(int argc, char * const argv[])
 }
 
 static int read_section(const struct ubigen_info *ui, const char *sname,
-			struct ubigen_vol_info *vi, const char **img,
-			struct stat *st)
+			struct ubigen_vol_info *vi)
 {
 	char buf[256];
 	const char *p;
+	struct stat st;
 
-	*img = NULL;
+	vi->image_file = NULL;
 
 	if (strlen(sname) > 128)
 		return errmsg("too long section name \"%s\"", sname);
@@ -294,13 +294,14 @@ static int read_section(const struct ubigen_info *ui, const char *sname,
 	sprintf(buf, "%s:image", sname);
 	p = iniparser_getstring(args.dict, buf, NULL);
 	if (p) {
-		*img = p;
-		if (stat(p, st))
+		vi->image_file = p;
+		if (stat(p, &st))
 			return sys_errmsg("cannot stat \"%s\" referred from section \"%s\"",
 					  p, sname);
-		if (st->st_size == 0)
+		if (st.st_size == 0)
 			return errmsg("empty file \"%s\" referred from section \"%s\"",
 				       p, sname);
+		vi->image_file_len = st.st_size;
 	} else if (vi->type == UBI_VID_STATIC)
 		return errmsg("image is not specified for static volume in section \"%s\"",
 			      sname);
@@ -329,24 +330,24 @@ static int read_section(const struct ubigen_info *ui, const char *sname,
 				      p, sname);
 
 		/* Make sure the image size is not larger than volume size */
-		if (*img && st->st_size > vi->bytes)
+		if (vi->image_file && st.st_size > vi->bytes)
 			return errmsg("error in section \"%s\": size of the image file "
 				      "\"%s\" is %lld, which is larger than volume size %lld",
-				      sname, *img, (long long)st->st_size, vi->bytes);
+				      sname, vi->image_file, (long long)st.st_size, vi->bytes);
 		verbose(args.verbose, "volume size: %lld bytes", vi->bytes);
 	} else {
-		if (!*img)
+		if (!vi->image_file)
 			return errmsg("neither image file (\"image=\") nor volume size "
 				      "(\"vol_size=\") specified in section \"%s\"", sname);
 
-		vi->bytes = st->st_size;
+		vi->bytes = st.st_size;
 
 		if (vi->bytes == 0)
 			return errmsg("file \"%s\" referred from section \"%s\" is empty",
-				      *img, sname);
+				      vi->image_file, sname);
 
 		normsg_cont("volume size was not specified in section \"%s\", assume"
-			    " minimum to fit image \"%s\"", sname, *img);
+			    " minimum to fit image \"%s\"", sname, vi->image_file);
 		util_print_bytes(vi->bytes, 1);
 		printf("\n");
 	}
@@ -395,7 +396,7 @@ static int read_section(const struct ubigen_info *ui, const char *sname,
 	if (vi->type == UBI_VID_DYNAMIC)
 		vi->used_ebs = (vi->bytes + vi->usable_leb_size - 1) / vi->usable_leb_size;
 	else
-		vi->used_ebs = (st->st_size + vi->usable_leb_size - 1) / vi->usable_leb_size;
+		vi->used_ebs = (st.st_size + vi->usable_leb_size - 1) / vi->usable_leb_size;
 	vi->compat = 0;
 	return 0;
 }
@@ -476,8 +477,6 @@ int main(int argc, char * const argv[])
 
 	for (i = 0; i < sects; i++) {
 		const char *sname = iniparser_getsecname(args.dict, i);
-		const char *img = NULL;
-		struct stat st;
 		int fd, j;
 
 		if (!sname) {
@@ -490,7 +489,7 @@ int main(int argc, char * const argv[])
 			printf("\n");
 		verbose(args.verbose, "parsing section \"%s\"", sname);
 
-		err = read_section(&ui, sname, &vi[i], &img, &st);
+		err = read_section(&ui, sname, &vi[i]);
 		if (err == -1)
 			goto out_free;
 
@@ -531,18 +530,18 @@ int main(int argc, char * const argv[])
 			goto out_free;
 		}
 
-		if (img) {
-			fd = open(img, O_RDONLY);
+		if (vi[i].image_file) {
+			fd = open(vi[i].image_file, O_RDONLY);
 			if (fd == -1) {
 				err = fd;
-				sys_errmsg("cannot open \"%s\"", img);
+				sys_errmsg("cannot open \"%s\"", vi[i].image_file);
 				goto out_free;
 			}
 
 			verbose(args.verbose, "writing volume %d", vi[i].id);
-			verbose(args.verbose, "image file: %s", img);
+			verbose(args.verbose, "image file: %s", vi[i].image_file);
 
-			err = ubigen_write_volume(&ui, &vi[i], args.ec, st.st_size, fd, args.out_fd);
+			err = ubigen_write_volume(&ui, &vi[i], args.ec, fd, args.out_fd);
 			close(fd);
 			if (err) {
 				errmsg("cannot write volume for section \"%s\"", sname);
-- 
2.13.6

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 4/5] libubigen: Maintain a eraseblock association table
  2018-05-14 11:25 [PATCH 0/5] mtd-utils: Add fastmap support to ubinize Richard Weinberger
                   ` (2 preceding siblings ...)
  2018-05-14 11:25 ` [PATCH 3/5] libubigen: Carry image path and size in volume info Richard Weinberger
@ 2018-05-14 11:25 ` Richard Weinberger
  2018-05-15 19:58   ` David Oberhollenzer
  2018-05-14 11:25 ` [PATCH 5/5] ubinize: Add fastmap support Richard Weinberger
  4 siblings, 1 reply; 8+ messages in thread
From: Richard Weinberger @ 2018-05-14 11:25 UTC (permalink / raw)
  To: linux-mtd; +Cc: linux-kernel, goliath, Richard Weinberger

The EBA is needed later for preseeded fastmap support.

Signed-off-by: Richard Weinberger <richard@nod.at>
---
 include/libubigen.h |  1 +
 lib/libubigen.c     | 14 ++++++++++++++
 ubi-utils/ubinize.c |  2 ++
 3 files changed, 17 insertions(+)

diff --git a/include/libubigen.h b/include/libubigen.h
index 8084d0ecddb2..6073a2d72e05 100644
--- a/include/libubigen.h
+++ b/include/libubigen.h
@@ -92,6 +92,7 @@ struct ubigen_vol_info
 	uint8_t flags;
 	const char *image_file;
 	size_t image_file_len;
+	int *eba;
 };
 
 /**
diff --git a/lib/libubigen.c b/lib/libubigen.c
index 900c984229fb..f509d4d072bd 100644
--- a/lib/libubigen.c
+++ b/lib/libubigen.c
@@ -176,6 +176,10 @@ int ubigen_write_volume(const struct ubigen_info *ui,
 	long long bytes = vi->image_file_len;
 	char *inbuf, *outbuf;
 
+	for (lnum = 0; lnum < vi->used_ebs; lnum++)
+		vi->eba[lnum] = -1;
+
+
 	if (vi->id >= ui->max_volumes) {
 		errmsg("too high volume id %d, max. volumes is %d",
 		       vi->id, ui->max_volumes);
@@ -203,6 +207,7 @@ int ubigen_write_volume(const struct ubigen_info *ui,
 	memset(outbuf, 0xFF, ui->data_offs);
 	ubigen_init_ec_hdr(ui, (struct ubi_ec_hdr *)outbuf, ec);
 
+	lnum = 0;
 	while (bytes) {
 		int l;
 		struct ubi_vid_hdr *vid_hdr;
@@ -229,6 +234,12 @@ int ubigen_write_volume(const struct ubigen_info *ui,
 		memset(outbuf + ui->data_offs + len, 0xFF,
 		       ui->peb_size - ui->data_offs - len);
 
+		vi->eba[lnum] = lseek(out, 0, SEEK_CUR) / ui->peb_size;
+		if (vi->eba[lnum] == -1) {
+			sys_errmsg("cannot get offset of output file");
+			goto out_free1;
+		}
+
 		if (write(out, outbuf, ui->peb_size) != ui->peb_size) {
 			sys_errmsg("cannot write %d bytes to the output file", ui->peb_size);
 			goto out_free1;
@@ -285,6 +296,7 @@ int ubigen_write_layout_vol(const struct ubigen_info *ui, int peb1, int peb2,
 		sys_errmsg("cannot seek output file");
 		goto out_free;
 	}
+	vi->eba[0] = peb1;
 
 	ubigen_init_ec_hdr(ui, (struct ubi_ec_hdr *)outbuf, ec1);
 	ubigen_init_vid_hdr(ui, &vi, vid_hdr, 0, NULL, 0);
@@ -299,6 +311,8 @@ int ubigen_write_layout_vol(const struct ubigen_info *ui, int peb1, int peb2,
 		sys_errmsg("cannot seek output file");
 		goto out_free;
 	}
+	vi->eba[1] = peb2;
+
 	ubigen_init_ec_hdr(ui, (struct ubi_ec_hdr *)outbuf, ec2);
 	ubigen_init_vid_hdr(ui, &vi, vid_hdr, 1, NULL, 0);
 	ret = write(fd, outbuf, ui->peb_size);
diff --git a/ubi-utils/ubinize.c b/ubi-utils/ubinize.c
index bffb66ebcbd9..62ddd7b85296 100644
--- a/ubi-utils/ubinize.c
+++ b/ubi-utils/ubinize.c
@@ -398,6 +398,7 @@ static int read_section(const struct ubigen_info *ui, const char *sname,
 	else
 		vi->used_ebs = (st.st_size + vi->usable_leb_size - 1) / vi->usable_leb_size;
 	vi->compat = 0;
+	vi->eba = xcalloc(vi->used_ebs, sizeof(int));
 	return 0;
 }
 
@@ -563,6 +564,7 @@ int main(int argc, char * const argv[])
 
 	verbose(args.verbose, "done");
 
+	free(vi->eba);
 	free(vi);
 	iniparser_freedict(args.dict);
 	free(vtbl);
-- 
2.13.6

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 5/5] ubinize: Add fastmap support
  2018-05-14 11:25 [PATCH 0/5] mtd-utils: Add fastmap support to ubinize Richard Weinberger
                   ` (3 preceding siblings ...)
  2018-05-14 11:25 ` [PATCH 4/5] libubigen: Maintain a eraseblock association table Richard Weinberger
@ 2018-05-14 11:25 ` Richard Weinberger
  4 siblings, 0 replies; 8+ messages in thread
From: Richard Weinberger @ 2018-05-14 11:25 UTC (permalink / raw)
  To: linux-mtd; +Cc: linux-kernel, goliath, Richard Weinberger

Using the "-F" parameter, ubinize can now create ubinized images
with a preseeded fastmap on it.
You need a recent kernel with UBI_FM_SB_PRESEEDED_FLG support to
attach from such a fastmap.

Signed-off-by: Richard Weinberger <richard@nod.at>
---
 include/libubigen.h   |  17 +++-
 lib/libubigen.c       | 224 ++++++++++++++++++++++++++++++++++++++++++++++----
 ubi-utils/ubiformat.c |   6 +-
 ubi-utils/ubinize.c   |  76 +++++++++++++----
 4 files changed, 283 insertions(+), 40 deletions(-)

diff --git a/include/libubigen.h b/include/libubigen.h
index 6073a2d72e05..7b50d903300c 100644
--- a/include/libubigen.h
+++ b/include/libubigen.h
@@ -110,6 +110,10 @@ void ubigen_info_init(struct ubigen_info *ui, int peb_size, int min_io_size,
 		      int subpage_size, int vid_hdr_offs, int ubi_ver,
 		      uint32_t image_seq);
 
+int ubigen_fastmap_size(struct ubigen_info *ui,
+			struct ubigen_vol_info *vols[], int vol_count,
+			struct ubigen_vol_info *layout_vol);
+
 /**
  * ubigen_create_empty_vtbl - creates empty volume table.
  * @ui: libubigen information
@@ -171,13 +175,18 @@ int ubigen_add_volume(const struct ubigen_info *ui,
  * writes the UBI volume to the output file @out. Returns zero on success and
  * %-1 on failure.
  */
-int ubigen_write_volume(const struct ubigen_info *ui,
+int ubigen_write_volume(struct ubigen_info *ui,
 			const struct ubigen_vol_info *vi, long long ec,
 			int in, int out);
 
+int ubigen_write_fastmap(struct ubigen_info *ui,
+			 struct ubigen_vol_info *layout_vi,
+			 int vol_count, struct ubigen_vol_info *vols[],
+			 int ec, int out_fd);
 /**
  * ubigen_write_layout_vol - write UBI layout volume
  * @ui: libubigen information
+ * @vi: volume information
  * @peb1: physical eraseblock number to write the first volume table copy
  * @peb2: physical eraseblock number to write the second volume table copy
  * @ec1: erase counter value for @peb1
@@ -188,10 +197,12 @@ int ubigen_write_volume(const struct ubigen_info *ui,
  * This function creates the UBI layout volume which contains 2 copies of the
  * volume table. Returns zero in case of success and %-1 in case of failure.
  */
-int ubigen_write_layout_vol(const struct ubigen_info *ui, int peb1, int peb2,
-			    long long ec1, long long ec2,
+int ubigen_write_layout_vol(struct ubigen_info *ui, struct ubigen_vol_info *vi,
+			    int peb1, int peb2, long long ec1, long long ec2,
 			    struct ubi_vtbl_record *vtbl, int fd);
 
+struct ubigen_vol_info *ubigen_init_layout_vi(const struct ubigen_info *ui);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/lib/libubigen.c b/lib/libubigen.c
index f509d4d072bd..05a27e639a49 100644
--- a/lib/libubigen.c
+++ b/lib/libubigen.c
@@ -30,13 +30,31 @@
 #include <stdint.h>
 #include <unistd.h>
 #include <string.h>
+#include <sys/param.h> /* roundup() */
 
 #include <mtd/ubi-media.h>
+#include <mtd/ubi-user.h>
 #include <mtd_swab.h>
 #include <libubigen.h>
 #include <crc32.h>
 #include "common.h"
 
+static size_t calc_fastmap_size(struct ubigen_info *ui, int peb_count)
+{
+	size_t size;
+
+	size = sizeof(struct ubi_fm_sb) +
+		sizeof(struct ubi_fm_hdr) +
+		sizeof(struct ubi_fm_scan_pool) +
+		sizeof(struct ubi_fm_scan_pool) +
+		(peb_count * sizeof(struct ubi_fm_ec)) +
+		(sizeof(struct ubi_fm_eba) +
+		(peb_count * sizeof(__be32))) +
+		sizeof(struct ubi_fm_volhdr) * UBI_MAX_VOLUMES;
+
+	return roundup(size, ui->leb_size);
+}
+
 void ubigen_info_init(struct ubigen_info *ui, int peb_size, int min_io_size,
 		      int subpage_size, int vid_hdr_offs, int ubi_ver,
 		      uint32_t image_seq)
@@ -63,6 +81,19 @@ void ubigen_info_init(struct ubigen_info *ui, int peb_size, int min_io_size,
 	ui->vtbl_size = ui->max_volumes * UBI_VTBL_RECORD_SIZE;
 }
 
+int ubigen_fastmap_size(struct ubigen_info *ui,
+			struct ubigen_vol_info *vols[], int vol_count,
+			struct ubigen_vol_info *layout_vol)
+{
+	int i;
+	int vol_pebs = layout_vol->used_ebs;
+
+	for (i = 0; i < vol_count; i++)
+		vol_pebs += vols[i]->used_ebs;
+
+	return calc_fastmap_size(ui, vol_pebs + UBI_FM_MAX_BLOCKS);
+}
+
 struct ubi_vtbl_record *ubigen_create_empty_vtbl(const struct ubigen_info *ui)
 {
 	struct ubi_vtbl_record *vtbl;
@@ -168,11 +199,31 @@ void ubigen_init_vid_hdr(const struct ubigen_info *ui,
 	hdr->hdr_crc = cpu_to_be32(crc);
 }
 
-int ubigen_write_volume(const struct ubigen_info *ui,
+static void ubigen_init_fm_vid_hdr(const struct ubigen_info *ui,
+				   struct ubi_vid_hdr *hdr, int vol_id,
+				   int lnum)
+{
+	uint32_t crc;
+
+	memset(hdr, 0, sizeof(struct ubi_vid_hdr));
+
+	hdr->magic = cpu_to_be32(UBI_VID_HDR_MAGIC);
+	hdr->version = ui->ubi_ver;
+	hdr->vol_type = UBI_VID_DYNAMIC;
+	hdr->vol_id = cpu_to_be32(vol_id);
+	hdr->lnum = cpu_to_be32(lnum);
+	hdr->compat = UBI_COMPAT_DELETE;
+	hdr->sqnum = cpu_to_be64(1);
+
+	crc = mtd_crc32(UBI_CRC32_INIT, hdr, UBI_VID_HDR_SIZE_CRC);
+	hdr->hdr_crc = cpu_to_be32(crc);
+}
+
+int ubigen_write_volume(struct ubigen_info *ui,
 			const struct ubigen_vol_info *vi, long long ec,
 			int in, int out)
 {
-	int len = vi->usable_leb_size, rd, lnum = 0;
+	int len = vi->usable_leb_size, rd, lnum;
 	long long bytes = vi->image_file_len;
 	char *inbuf, *outbuf;
 
@@ -259,27 +310,144 @@ out_free:
 	return -1;
 }
 
-int ubigen_write_layout_vol(const struct ubigen_info *ui, int peb1, int peb2,
-			    long long ec1, long long ec2,
+int ubigen_write_fastmap(struct ubigen_info *ui,
+			 struct ubigen_vol_info *layout_vi,
+			 int vol_count, struct ubigen_vol_info *vols[],
+			 int ec, int out_fd)
+{
+	int i, j, ret;
+	struct ubi_fm_sb *fmsb;
+	struct ubi_fm_hdr *fmh;
+	struct ubi_fm_scan_pool *fmpl, *fmpl_wl;
+	struct ubi_fm_ec *fec;
+	struct ubi_fm_volhdr *fvh;
+	struct ubi_fm_eba *feba;
+	struct ubigen_vol_info *vi;
+	size_t fm_pos = 0;
+	size_t fm_size = ubigen_fastmap_size(ui, vols, vol_count, layout_vi);
+	char *fm_raw = xcalloc(1, fm_size);
+	char *peb_buf = xmalloc(ui->peb_size);
+	int fm_pebs = fm_size / ui->leb_size;
+	int pebs_used = 0;
+
+
+	fmsb = (struct ubi_fm_sb *)fm_raw;
+	fm_pos += sizeof(*fmsb);
+
+	fmsb->magic = cpu_to_be32(UBI_FM_SB_MAGIC);
+	fmsb->version = 2;
+	fmsb->used_blocks = cpu_to_be32(fm_pebs);
+	fmsb->sqnum = 0;
+	fmsb->data_crc = 0;
+	fmsb->flags = cpu_to_be32(UBI_FM_SB_PRESEEDED_FLG);
+
+	for (i = 0; i < fm_pebs; i++) {
+		fmsb->block_loc[i] = cpu_to_be32(layout_vi->used_ebs + i);
+		fmsb->block_ec[i] = cpu_to_be32(ec);
+	}
+
+	fmh = (struct ubi_fm_hdr *)(fm_raw + fm_pos);
+	fm_pos += sizeof(*fmh);
+
+	fmh->magic = cpu_to_be32(UBI_FM_HDR_MAGIC);
+	fmh->vol_count = cpu_to_be32(vol_count + 1);
+	fmh->free_peb_count = 0;
+	fmh->scrub_peb_count = 0;
+	fmh->erase_peb_count = 0;
+	fmh->bad_peb_count = 0;
+
+	fmpl = (struct ubi_fm_scan_pool *)(fm_raw + fm_pos);
+	fm_pos += sizeof(*fmpl);
+
+	fmpl->magic = cpu_to_be32(UBI_FM_POOL_MAGIC);
+	fmpl->size = 0;
+	fmpl->max_size = 0;
+
+	fmpl_wl = (struct ubi_fm_scan_pool *)(fm_raw + fm_pos);
+	fm_pos += sizeof(*fmpl_wl);
+
+	fmpl_wl->magic = cpu_to_be32(UBI_FM_POOL_MAGIC);
+        fmpl_wl->size = 0;
+        fmpl_wl->max_size = 0;
+
+	for (i = 0; i < vol_count + 1; i++) {
+		if (i == vol_count)
+			vi = layout_vi;
+		else
+			vi = vols[i];
+
+		for (j = 0; j < vi->used_ebs; j++) {
+			fec = (struct ubi_fm_ec *)(fm_raw + fm_pos);
+
+			if (vi->eba[j] > -1) {
+				fec->pnum = cpu_to_be32(vi->eba[j]);
+				fec->ec = cpu_to_be32(ec);
+				pebs_used++;
+				fm_pos += sizeof(*fec);
+			}
+		}
+	}
+
+	fmh->used_peb_count = cpu_to_be32(pebs_used);
+
+	for (i = 0; i < vol_count + 1; i++) {
+		if (i == vol_count)
+			vi = layout_vi;
+		else
+			vi = vols[i];
+
+		fvh = (struct ubi_fm_volhdr *)(fm_raw + fm_pos);
+		fm_pos += sizeof(*fvh);
+
+		fvh->magic = cpu_to_be32(UBI_FM_VHDR_MAGIC);
+		fvh->vol_id = cpu_to_be32(vi->id);
+		fvh->vol_type = vi->type == UBI_VID_DYNAMIC ? UBI_DYNAMIC_VOLUME : UBI_STATIC_VOLUME;
+		fvh->used_ebs = cpu_to_be32(vi->used_ebs);
+		fvh->data_pad = cpu_to_be32(vi->data_pad);
+		fvh->last_eb_bytes = cpu_to_be32(vi->bytes % vi->usable_leb_size);
+
+		feba = (struct ubi_fm_eba *)(fm_raw + fm_pos);
+		fm_pos += sizeof(*feba) + (sizeof(__be32) * vi->used_ebs);
+
+		feba->magic = cpu_to_be32(UBI_FM_EBA_MAGIC);
+		feba->reserved_pebs = cpu_to_be32(vi->used_ebs);
+		for (j = 0; j < vi->used_ebs; j++)
+			feba->pnum[j] = cpu_to_be32(vi->eba[j]);
+	}
+
+	fmsb->data_crc = cpu_to_be32(mtd_crc32(UBI_CRC32_INIT, fm_raw, fm_size));
+
+	for (i = 0; i < fm_pebs; i++) {
+		int vol_id = i == 0 ? UBI_FM_SB_VOLUME_ID : UBI_FM_DATA_VOLUME_ID;
+
+		memset(peb_buf, 0xff, ui->peb_size);
+
+		ubigen_init_ec_hdr(ui, (struct ubi_ec_hdr *)peb_buf, ec);
+		ubigen_init_fm_vid_hdr(ui, (struct ubi_vid_hdr *)(peb_buf + ui->vid_hdr_offs), vol_id, i);
+		memcpy(peb_buf + ui->data_offs, fm_raw + ui->leb_size * i, ui->leb_size);
+		ret = write(out_fd, peb_buf, ui->peb_size);
+		if (ret != ui->peb_size) {
+			sys_errmsg("cannot write %d bytes", ui->peb_size);
+			goto out;
+		}
+	}
+
+	ret = 0;
+out:
+	free(fm_raw);
+	free(peb_buf);
+	return ret;
+}
+
+int ubigen_write_layout_vol(struct ubigen_info *ui, struct ubigen_vol_info *vi,
+			    int peb1, int peb2, long long ec1, long long ec2,
 			    struct ubi_vtbl_record *vtbl, int fd)
 {
 	int ret;
-	struct ubigen_vol_info vi;
 	char *outbuf;
 	struct ubi_vid_hdr *vid_hdr;
 	off_t seek;
 
-	vi.bytes = ui->leb_size * UBI_LAYOUT_VOLUME_EBS;
-	vi.id = UBI_LAYOUT_VOLUME_ID;
-	vi.alignment = UBI_LAYOUT_VOLUME_ALIGN;
-	vi.data_pad = ui->leb_size % UBI_LAYOUT_VOLUME_ALIGN;
-	vi.usable_leb_size = ui->leb_size - vi.data_pad;
-	vi.data_pad = ui->leb_size - vi.usable_leb_size;
-	vi.type = UBI_LAYOUT_VOLUME_TYPE;
-	vi.name = UBI_LAYOUT_VOLUME_NAME;
-	vi.name_len = strlen(UBI_LAYOUT_VOLUME_NAME);
-	vi.compat = UBI_LAYOUT_VOLUME_COMPAT;
-
 	outbuf = malloc(ui->peb_size);
 	if (!outbuf)
 		return sys_errmsg("failed to allocate %d bytes",
@@ -299,7 +467,7 @@ int ubigen_write_layout_vol(const struct ubigen_info *ui, int peb1, int peb2,
 	vi->eba[0] = peb1;
 
 	ubigen_init_ec_hdr(ui, (struct ubi_ec_hdr *)outbuf, ec1);
-	ubigen_init_vid_hdr(ui, &vi, vid_hdr, 0, NULL, 0);
+	ubigen_init_vid_hdr(ui, vi, vid_hdr, 0, NULL, 0);
 	ret = write(fd, outbuf, ui->peb_size);
 	if (ret != ui->peb_size) {
 		sys_errmsg("cannot write %d bytes", ui->peb_size);
@@ -314,7 +482,7 @@ int ubigen_write_layout_vol(const struct ubigen_info *ui, int peb1, int peb2,
 	vi->eba[1] = peb2;
 
 	ubigen_init_ec_hdr(ui, (struct ubi_ec_hdr *)outbuf, ec2);
-	ubigen_init_vid_hdr(ui, &vi, vid_hdr, 1, NULL, 0);
+	ubigen_init_vid_hdr(ui, vi, vid_hdr, 1, NULL, 0);
 	ret = write(fd, outbuf, ui->peb_size);
 	if (ret != ui->peb_size) {
 		sys_errmsg("cannot write %d bytes", ui->peb_size);
@@ -328,3 +496,23 @@ out_free:
 	free(outbuf);
 	return -1;
 }
+
+struct ubigen_vol_info *ubigen_init_layout_vi(const struct ubigen_info *ui)
+{
+	struct ubigen_vol_info *vi = xmalloc(sizeof(*vi));
+
+	vi->bytes = ui->leb_size * UBI_LAYOUT_VOLUME_EBS;
+	vi->id = UBI_LAYOUT_VOLUME_ID;
+	vi->alignment = UBI_LAYOUT_VOLUME_ALIGN;
+	vi->data_pad = ui->leb_size % UBI_LAYOUT_VOLUME_ALIGN;
+	vi->usable_leb_size = ui->leb_size - vi->data_pad;
+	vi->data_pad = ui->leb_size - vi->usable_leb_size;
+	vi->type = UBI_LAYOUT_VOLUME_TYPE;
+	vi->name = UBI_LAYOUT_VOLUME_NAME;
+	vi->name_len = strlen(UBI_LAYOUT_VOLUME_NAME);
+	vi->compat = UBI_LAYOUT_VOLUME_COMPAT;
+	vi->used_ebs = 2;
+	vi->eba = xcalloc(vi->used_ebs, sizeof(int));
+
+	return vi;
+}
diff --git a/ubi-utils/ubiformat.c b/ubi-utils/ubiformat.c
index c38b9b4abb16..a333246ecf77 100644
--- a/ubi-utils/ubiformat.c
+++ b/ubi-utils/ubiformat.c
@@ -553,7 +553,7 @@ out_close:
 }
 
 static int format(libmtd_t libmtd, const struct mtd_dev_info *mtd,
-		  const struct ubigen_info *ui, struct ubi_scan_info *si,
+		  struct ubigen_info *ui, struct ubi_scan_info *si,
 		  int start_eb, int novtbl)
 {
 	int eb, err, write_size;
@@ -655,6 +655,8 @@ static int format(libmtd_t libmtd, const struct mtd_dev_info *mtd,
 		printf("\n");
 
 	if (!novtbl) {
+		struct ubigen_vol_info *layout_vi = ubigen_init_layout_vi(ui);
+
 		if (eb1 == -1 || eb2 == -1) {
 			errmsg("no eraseblocks for volume table");
 			goto out_free;
@@ -665,7 +667,7 @@ static int format(libmtd_t libmtd, const struct mtd_dev_info *mtd,
 		if (!vtbl)
 			goto out_free;
 
-		err = ubigen_write_layout_vol(ui, eb1, eb2, ec1,  ec2, vtbl,
+		err = ubigen_write_layout_vol(ui, layout_vi, eb1, eb2, ec1,  ec2, vtbl,
 					      args.node_fd);
 		free(vtbl);
 		if (err) {
diff --git a/ubi-utils/ubinize.c b/ubi-utils/ubinize.c
index 62ddd7b85296..08048eceb33a 100644
--- a/ubi-utils/ubinize.c
+++ b/ubi-utils/ubinize.c
@@ -82,6 +82,7 @@ static const struct option long_options[] = {
 	{ .name = "verbose",        .has_arg = 0, .flag = NULL, .val = 'v' },
 	{ .name = "help",           .has_arg = 0, .flag = NULL, .val = 'h' },
 	{ .name = "version",        .has_arg = 0, .flag = NULL, .val = 'V' },
+	{ .name = "fastmap",        .has_arg = 0, .flag = NULL, .val = 'F' },
 	{ NULL, 0, NULL, 0}
 };
 
@@ -97,6 +98,7 @@ struct args {
 	int ubi_ver;
 	uint32_t image_seq;
 	int verbose;
+	int fastmap;
 	dictionary *dict;
 };
 
@@ -116,7 +118,7 @@ static int parse_opt(int argc, char * const argv[])
 		int key, error = 0;
 		unsigned long int image_seq;
 
-		key = getopt_long(argc, argv, "o:p:m:s:O:e:x:Q:vhV", long_options, NULL);
+		key = getopt_long(argc, argv, "o:p:m:s:O:e:x:Q:vhVF", long_options, NULL);
 		if (key == -1)
 			break;
 
@@ -180,6 +182,10 @@ static int parse_opt(int argc, char * const argv[])
 			args.verbose = 1;
 			break;
 
+		case 'F':
+			args.fastmap = 1;
+			break;
+
 		case 'h':
 			fputs(usage, stdout);
 			fputs(optionsstr, stdout);
@@ -408,6 +414,7 @@ int main(int argc, char * const argv[])
 	struct ubigen_info ui;
 	struct ubi_vtbl_record *vtbl;
 	struct ubigen_vol_info *vi;
+	struct ubigen_vol_info *layout_vi;
 	off_t seek;
 
 	err = parse_opt(argc, argv);
@@ -465,20 +472,11 @@ int main(int argc, char * const argv[])
 		goto out_dict;
 	}
 
-	/*
-	 * Skip 2 PEBs at the beginning of the file for the volume table which
-	 * will be written later.
-	 */
-	seek = ui.peb_size * 2;
-	if (lseek(args.out_fd, seek, SEEK_SET) != seek) {
-		err = -1;
-		sys_errmsg("cannot seek file \"%s\"", args.f_out);
-		goto out_free;
-	}
+	layout_vi = ubigen_init_layout_vi(&ui);
 
 	for (i = 0; i < sects; i++) {
 		const char *sname = iniparser_getsecname(args.dict, i);
-		int fd, j;
+		int j;
 
 		if (!sname) {
 			err = -1;
@@ -531,8 +529,33 @@ int main(int argc, char * const argv[])
 			goto out_free;
 		}
 
+		if (args.verbose)
+			printf("\n");
+	}
+
+	/*
+	 * Skip 2 PEBs at the beginning of the file for the volume table which
+	 * will be written later.
+	 */
+	seek = 2;
+
+	/*
+	 * If Fastmap is enabled we need also some PEBs for it at the beginning.
+	 */
+	if (args.fastmap)
+		seek += ubigen_fastmap_size(&ui, &vi, sects, layout_vi) / ui.leb_size;
+
+	seek *= ui.peb_size;
+
+	if (lseek(args.out_fd, seek, SEEK_SET) != seek) {
+		err = -1;
+		sys_errmsg("cannot seek file \"%s\"", args.f_out);
+		goto out_free;
+	}
+
+	for (i = 0; i < sects; i++) {
 		if (vi[i].image_file) {
-			fd = open(vi[i].image_file, O_RDONLY);
+			int fd = open(vi[i].image_file, O_RDONLY);
 			if (fd == -1) {
 				err = fd;
 				sys_errmsg("cannot open \"%s\"", vi[i].image_file);
@@ -545,27 +568,44 @@ int main(int argc, char * const argv[])
 			err = ubigen_write_volume(&ui, &vi[i], args.ec, fd, args.out_fd);
 			close(fd);
 			if (err) {
-				errmsg("cannot write volume for section \"%s\"", sname);
+				errmsg("cannot write volume \"%s\"", vi[i].name);
 				goto out_free;
 			}
 		}
 
-		if (args.verbose)
-			printf("\n");
 	}
 
 	verbose(args.verbose, "writing layout volume");
 
-	err = ubigen_write_layout_vol(&ui, 0, 1, args.ec, args.ec, vtbl, args.out_fd);
+	err = ubigen_write_layout_vol(&ui, layout_vi, 0, 1, args.ec, args.ec, vtbl, args.out_fd);
 	if (err) {
 		errmsg("cannot write layout volume");
 		goto out_free;
 	}
 
+	if (args.fastmap) {
+		verbose(args.verbose, "writing fastmap");
+
+		if (lseek(args.out_fd, 2 * ui.peb_size, SEEK_SET) != 2 * ui.peb_size) {
+			err = -1;
+			sys_errmsg("cannot seek file \"%s\"", args.f_out);
+			goto out_free;
+		}
+
+		err = ubigen_write_fastmap(&ui, layout_vi, sects, &vi, args.ec, args.out_fd);
+		if (err) {
+			errmsg("cannot write fastmap");
+			goto out_free;
+		}
+	}
+
+
 	verbose(args.verbose, "done");
 
 	free(vi->eba);
 	free(vi);
+	free(layout_vi->eba);
+	free(layout_vi);
 	iniparser_freedict(args.dict);
 	free(vtbl);
 	close(args.out_fd);
@@ -573,6 +613,8 @@ int main(int argc, char * const argv[])
 
 out_free:
 	free(vi);
+	free(layout_vi);
+	free(layout_vi->eba);
 out_dict:
 	iniparser_freedict(args.dict);
 out_vtbl:
-- 
2.13.6

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [PATCH 4/5] libubigen: Maintain a eraseblock association table
  2018-05-14 11:25 ` [PATCH 4/5] libubigen: Maintain a eraseblock association table Richard Weinberger
@ 2018-05-15 19:58   ` David Oberhollenzer
  2018-05-15 20:22     ` Richard Weinberger
  0 siblings, 1 reply; 8+ messages in thread
From: David Oberhollenzer @ 2018-05-15 19:58 UTC (permalink / raw)
  To: Richard Weinberger, linux-mtd; +Cc: linux-kernel

On 05/14/2018 01:25 PM, Richard Weinberger wrote:
> @@ -229,6 +234,12 @@ int ubigen_write_volume(const struct ubigen_info *ui,
>  		memset(outbuf + ui->data_offs + len, 0xFF,
>  		       ui->peb_size - ui->data_offs - len);
>  
> +		vi->eba[lnum] = lseek(out, 0, SEEK_CUR) / ui->peb_size;
> +		if (vi->eba[lnum] == -1) {
> +			sys_errmsg("cannot get offset of output file");
> +			goto out_free1;
> +		}
> +
>  		if (write(out, outbuf, ui->peb_size) != ui->peb_size) {
>  			sys_errmsg("cannot write %d bytes to the output file", ui->peb_size);
>  			goto out_free1;

Wouldn't that division swallow errors? If I interpret the C99 draft correctly, dividing
an lseek return value of -1 by ui->peb_size > 1 should result in 0.

Thanks,

David

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH 4/5] libubigen: Maintain a eraseblock association table
  2018-05-15 19:58   ` David Oberhollenzer
@ 2018-05-15 20:22     ` Richard Weinberger
  0 siblings, 0 replies; 8+ messages in thread
From: Richard Weinberger @ 2018-05-15 20:22 UTC (permalink / raw)
  To: David Oberhollenzer; +Cc: linux-mtd, linux-kernel

Am Dienstag, 15. Mai 2018, 21:58:01 CEST schrieb David Oberhollenzer:
> On 05/14/2018 01:25 PM, Richard Weinberger wrote:
> > @@ -229,6 +234,12 @@ int ubigen_write_volume(const struct ubigen_info *ui,
> >  		memset(outbuf + ui->data_offs + len, 0xFF,
> >  		       ui->peb_size - ui->data_offs - len);
> >  
> > +		vi->eba[lnum] = lseek(out, 0, SEEK_CUR) / ui->peb_size;
> > +		if (vi->eba[lnum] == -1) {
> > +			sys_errmsg("cannot get offset of output file");
> > +			goto out_free1;
> > +		}
> > +
> >  		if (write(out, outbuf, ui->peb_size) != ui->peb_size) {
> >  			sys_errmsg("cannot write %d bytes to the output file", ui->peb_size);
> >  			goto out_free1;
> 
> Wouldn't that division swallow errors? If I interpret the C99 draft correctly, dividing
> an lseek return value of -1 by ui->peb_size > 1 should result in 0.

Yep, that needs fixing.

Thanks,
//richard

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2018-05-15 20:22 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-05-14 11:25 [PATCH 0/5] mtd-utils: Add fastmap support to ubinize Richard Weinberger
2018-05-14 11:25 ` [PATCH 1/5] Sync ubi-media.h with Linux Richard Weinberger
2018-05-14 11:25 ` [PATCH 2/5] ubinize: Don't stat image file twice Richard Weinberger
2018-05-14 11:25 ` [PATCH 3/5] libubigen: Carry image path and size in volume info Richard Weinberger
2018-05-14 11:25 ` [PATCH 4/5] libubigen: Maintain a eraseblock association table Richard Weinberger
2018-05-15 19:58   ` David Oberhollenzer
2018-05-15 20:22     ` Richard Weinberger
2018-05-14 11:25 ` [PATCH 5/5] ubinize: Add fastmap support Richard Weinberger

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.