]> www.infradead.org Git - mtd-utils.git/commitdiff
ubi-utils: save libubigen
authorArtem Bityutskiy <Artem.Bityutskiy@nokia.com>
Fri, 18 Jan 2008 18:03:16 +0000 (20:03 +0200)
committerArtem Bityutskiy <Artem.Bityutskiy@nokia.com>
Fri, 18 Jan 2008 18:03:16 +0000 (20:03 +0200)
I'm going to change libubigen so saving the old one in sort-me-out.

Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
ubi-utils/sort-me-out/README
ubi-utils/sort-me-out/libubigen-old.c [new file with mode: 0644]
ubi-utils/sort-me-out/ubigen.c

index fa09c966607f4f22d263e2fe27589dbf6d9e5e9b..384322b04de27ab2a921a1a1008a91011892bcb8 100644 (file)
@@ -63,3 +63,6 @@ This directory contains various stuff that has to be cleaned up and sorted out.
   cleaned-up and moved to src/
 
 * error.[ch]: strange and rather IBM-specific error messages output infrastructure.
+
+* libubigen-old.c: old ubigen library other tools in this directory should be
+  compiled with
diff --git a/ubi-utils/sort-me-out/libubigen-old.c b/ubi-utils/sort-me-out/libubigen-old.c
new file mode 100644 (file)
index 0000000..6aef291
--- /dev/null
@@ -0,0 +1,486 @@
+/*
+ * Copyright (c) International Business Machines Corp., 2006
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Author: Oliver Lohmann
+ *
+ * Add UBI headers to binary data.
+ */
+
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <mtd/ubi-header.h>
+
+#include "config.h"
+#include "ubigen.h"
+#include "crc32.h"
+
+#define UBI_NAME_SIZE          256
+#define DEFAULT_VID_OFFSET     ((DEFAULT_PAGESIZE) - (UBI_VID_HDR_SIZE))
+#define MIN(a,b)               ((a) < (b) ? (a) : (b))
+
+static uint32_t crc32_table[256];
+
+struct ubi_info {
+       struct ubi_vid_hdr* v;  /* Volume ID header */
+       struct ubi_ec_hdr* ec;  /* Erase count header */
+
+       FILE* fp_in;            /* Input Stream */
+       FILE* fp_out;           /* Output stream */
+
+       size_t peb_size;        /* Physical EB size in bytes */
+       size_t leb_size;        /* Size of a logical EB in a physical EB */
+       size_t leb_total;       /* Total input size in logical EB */
+       size_t alignment;       /* Block alignment */
+       size_t data_pad;        /* Size of padding in each physical EB */
+
+       size_t bytes_total;     /* Total input size in bytes */
+       size_t bytes_read;      /* Nymber of read bytes (total) */
+
+       uint32_t blks_written;  /* Number of written logical EB */
+
+       uint8_t* buf;           /* Allocated buffer */
+       uint8_t* ptr_ec_hdr;    /* Pointer to EC hdr in buf */
+       uint8_t* ptr_vid_hdr;   /* Pointer to VID hdr in buf */
+       uint8_t* ptr_data;      /* Pointer to data region in buf */
+};
+
+
+static uint32_t
+byte_to_blk(uint64_t byte, uint32_t peb_size)
+{
+       return (byte % peb_size) == 0
+               ? (byte / peb_size)
+               : (byte / peb_size) + 1;
+}
+
+static int
+validate_ubi_info(ubi_info_t u)
+{
+       if ((u->v->vol_type != UBI_VID_DYNAMIC) &&
+           (u->v->vol_type != UBI_VID_STATIC)) {
+               return EUBIGEN_INVALID_TYPE;
+       }
+
+       if (__be32_to_cpu(u->ec->vid_hdr_offset) < UBI_VID_HDR_SIZE) {
+               return EUBIGEN_INVALID_HDR_OFFSET;
+       }
+
+       return 0;
+}
+
+static int
+skip_blks(ubi_info_t u, uint32_t blks)
+{
+       uint32_t i;
+       size_t read = 0, to_read = 0;
+
+       /* Step to a maximum of leb_total - 1 to keep the
+          restrictions. */
+       for (i = 0; i < MIN(blks, u->leb_total-1); i++) {
+               /* Read in data */
+               to_read = MIN(u->leb_size,
+                             (u->bytes_total - u->bytes_read));
+               read = fread(u->ptr_data, 1, to_read, u->fp_in);
+               if (read != to_read) {
+                       return -EIO;
+               }
+               u->bytes_read += read;
+               u->blks_written++;
+       }
+
+       return 0;
+}
+
+static void
+clear_buf(ubi_info_t u)
+{
+       memset(u->buf, 0xff, u->peb_size);
+}
+
+static void
+write_ec_hdr(ubi_info_t u)
+{
+       memcpy(u->ptr_ec_hdr, u->ec, UBI_EC_HDR_SIZE);
+}
+
+static int
+fill_data_buffer_from_file(ubi_info_t u, size_t* read)
+{
+       size_t to_read = 0;
+
+       if (u-> fp_in == NULL)
+               return -EIO;
+
+       to_read = MIN(u->leb_size, (u->bytes_total - u->bytes_read));
+       *read = fread(u->ptr_data, 1, to_read, u->fp_in);
+       if (*read != to_read) {
+               return -EIO;
+       }
+       return 0;
+}
+
+static void
+add_static_info(ubi_info_t u, size_t data_size, ubigen_action_t action)
+{
+       uint32_t crc = clc_crc32(crc32_table, UBI_CRC32_INIT,
+                                u->ptr_data, data_size);
+
+       u->v->data_size = __cpu_to_be32(data_size);
+       u->v->data_crc = __cpu_to_be32(crc);
+
+       if (action & BROKEN_DATA_CRC) {
+               u->v->data_crc =
+                       __cpu_to_be32(__be32_to_cpu(u->v->data_crc) + 1);
+       }
+       if (action & BROKEN_DATA_SIZE) {
+               u->v->data_size =
+                       __cpu_to_be32(__be32_to_cpu(u->v->data_size) + 1);
+       }
+}
+
+static void
+write_vid_hdr(ubi_info_t u, ubigen_action_t action)
+{
+       uint32_t crc = clc_crc32(crc32_table, UBI_CRC32_INIT,
+                                u->v, UBI_VID_HDR_SIZE_CRC);
+       /* Write VID header */
+       u->v->hdr_crc = __cpu_to_be32(crc);
+       if (action & BROKEN_HDR_CRC) {
+               u->v->hdr_crc = __cpu_to_be32(__be32_to_cpu(u->v->hdr_crc) + 1);
+       }
+       memcpy(u->ptr_vid_hdr, u->v, UBI_VID_HDR_SIZE);
+}
+
+static int
+write_to_output_stream(ubi_info_t u)
+{
+       size_t written;
+
+       written = fwrite(u->buf, 1, u->peb_size, u->fp_out);
+       if (written != u->peb_size) {
+               return -EIO;
+       }
+       return 0;
+}
+
+int
+ubigen_write_leb(ubi_info_t u, ubigen_action_t action)
+{
+       int rc = 0;
+       size_t read = 0;
+
+       clear_buf(u);
+       write_ec_hdr(u);
+
+       rc = fill_data_buffer_from_file(u, &read);
+       if (rc != 0)
+               return rc;
+
+       if (u->v->vol_type == UBI_VID_STATIC)  {
+               add_static_info(u, read, action);
+       }
+
+       u->v->lnum = __cpu_to_be32(u->blks_written);
+
+       if (action & MARK_AS_UPDATE) {
+               u->v->copy_flag = (u->v->copy_flag)++;
+       }
+
+       write_vid_hdr(u, action);
+       rc = write_to_output_stream(u);
+       if (rc != 0)
+               return rc;
+
+       /* Update current handle */
+       u->bytes_read += read;
+       u->blks_written++;
+       return 0;
+}
+
+int
+ubigen_write_complete(ubi_info_t u)
+{
+       size_t i;
+       int rc = 0;
+
+       for (i = 0; i < u->leb_total; i++) {
+               rc = ubigen_write_leb(u,  NO_ERROR);
+               if (rc != 0)
+                       return rc;
+       }
+
+       return 0;
+}
+
+int
+ubigen_write_broken_update(ubi_info_t u, uint32_t blk)
+{
+       int rc = 0;
+
+       rc = skip_blks(u, blk);
+       if (rc != 0)
+               return rc;
+
+       rc = ubigen_write_leb(u, MARK_AS_UPDATE | BROKEN_DATA_CRC);
+       if (rc != 0)
+               return rc;
+
+
+       return 0;
+}
+
+void
+dump_info(ubi_info_t u ubi_unused)
+{
+#ifdef DEBUG
+       int err = 0;
+       if (!u) {
+               fprintf(stderr, "<empty>");
+               return;
+       }
+       if (!u->ec) {
+               fprintf(stderr, "<ec-empty>");
+               err = 1;
+       }
+       if (!u->v) {
+               fprintf(stderr, "<v-empty>");
+               err = 1;
+       }
+       if (err) return;
+
+       fprintf(stderr, "ubi volume\n");
+       fprintf(stderr, "version      :   %8d\n", u->v->version);
+       fprintf(stderr, "vol_id       :   %8d\n", __be32_to_cpu(u->v->vol_id));
+       fprintf(stderr, "vol_type     :   %8s\n",
+               u->v->vol_type == UBI_VID_STATIC ?
+               "static" : "dynamic");
+       fprintf(stderr, "used_ebs     :   %8d\n",
+               __be32_to_cpu(u->v->used_ebs));
+       fprintf(stderr, "peb_size     : 0x%08x\n", u->peb_size);
+       fprintf(stderr, "leb_size     : 0x%08x\n", u->leb_size);
+       fprintf(stderr, "data_pad     : 0x%08x\n",
+               __be32_to_cpu(u->v->data_pad));
+       fprintf(stderr, "leb_total    :   %8d\n", u->leb_total);
+       fprintf(stderr, "header offs  : 0x%08x\n",
+               __be32_to_cpu(u->ec->vid_hdr_offset));
+       fprintf(stderr, "bytes_total  :   %8d\n", u->bytes_total);
+       fprintf(stderr, "  +  in MiB  : %8.2f M\n",
+               ((float)(u->bytes_total)) / 1024 / 1024);
+       fprintf(stderr, "-------------------------------\n\n");
+#else
+       return;
+#endif
+}
+
+int
+ubigen_destroy(ubi_info_t *u)
+{
+       if (u == NULL)
+               return -EINVAL;
+
+       ubi_info_t tmp = *u;
+
+       if (tmp) {
+               if (tmp->v)
+                       free(tmp->v);
+               if (tmp->ec)
+                       free(tmp->ec);
+               if (tmp->buf)
+                       free(tmp->buf);
+               free(tmp);
+       }
+       *u = NULL;
+       return 0;
+}
+
+void
+ubigen_init(void)
+{
+       init_crc32_table(crc32_table);
+}
+
+int
+ubigen_create(ubi_info_t* u, uint32_t vol_id, uint8_t vol_type,
+             uint32_t peb_size, uint64_t ec, uint32_t alignment,
+             uint8_t version, uint32_t vid_hdr_offset, uint8_t compat_flag,
+             size_t data_size, FILE* fp_in, FILE* fp_out)
+{
+       int rc = 0;
+       ubi_info_t res = NULL;
+       uint32_t crc;
+       uint32_t data_offset;
+
+       if (alignment == 0) {
+               rc = EUBIGEN_INVALID_ALIGNMENT;
+               goto ubigen_create_err;
+       }
+       if ((fp_in == NULL) || (fp_out == NULL)) {
+               rc = -EINVAL;
+               goto ubigen_create_err;
+       }
+
+       res = (ubi_info_t) calloc(1, sizeof(struct ubi_info));
+       if (res == NULL) {
+               rc = -ENOMEM;
+               goto ubigen_create_err;
+       }
+
+       res->v = (struct ubi_vid_hdr*) calloc(1, sizeof(struct ubi_vid_hdr));
+       if (res->v == NULL) {
+               rc = -ENOMEM;
+               goto ubigen_create_err;
+       }
+
+       res->ec = (struct ubi_ec_hdr*) calloc(1, sizeof(struct ubi_ec_hdr));
+       if (res->ec == NULL) {
+               rc = -ENOMEM;
+               goto ubigen_create_err;
+       }
+
+       /* data which is needed in the general process */
+       vid_hdr_offset = vid_hdr_offset ? vid_hdr_offset : DEFAULT_VID_OFFSET;
+       data_offset = vid_hdr_offset + UBI_VID_HDR_SIZE;
+       res->bytes_total = data_size;
+       res->peb_size = peb_size ? peb_size : DEFAULT_BLOCKSIZE;
+       res->data_pad = (res->peb_size - data_offset) % alignment;
+       res->leb_size = res->peb_size - data_offset - res->data_pad;
+       res->leb_total = byte_to_blk(data_size, res->leb_size);
+       res->alignment = alignment;
+
+       if ((res->peb_size < (vid_hdr_offset + UBI_VID_HDR_SIZE))) {
+               rc = EUBIGEN_TOO_SMALL_EB;
+               goto ubigen_create_err;
+       }
+       res->fp_in = fp_in;
+       res->fp_out = fp_out;
+
+       /* vid hdr data which doesn't change */
+       res->v->magic = __cpu_to_be32(UBI_VID_HDR_MAGIC);
+       res->v->version = version ? version : UBI_VERSION;
+       res->v->vol_type = vol_type;
+       res->v->vol_id = __cpu_to_be32(vol_id);
+       res->v->compat = compat_flag;
+       res->v->data_pad = __cpu_to_be32(res->data_pad);
+
+       /* static only: used_ebs */
+       if (res->v->vol_type == UBI_VID_STATIC) {
+               res->v->used_ebs = __cpu_to_be32(byte_to_blk
+                                               (res->bytes_total,
+                                                res->leb_size));
+       }
+
+       /* ec hdr (fixed, doesn't change) */
+       res->ec->magic = __cpu_to_be32(UBI_EC_HDR_MAGIC);
+       res->ec->version = version ? version : UBI_VERSION;
+       res->ec->ec = __cpu_to_be64(ec);
+       res->ec->vid_hdr_offset = __cpu_to_be32(vid_hdr_offset);
+
+       res->ec->data_offset = __cpu_to_be32(data_offset);
+
+       crc = clc_crc32(crc32_table, UBI_CRC32_INIT, res->ec,
+                       UBI_EC_HDR_SIZE_CRC);
+       res->ec->hdr_crc = __cpu_to_be32(crc);
+
+       /* prepare a read buffer */
+       res->buf = (uint8_t*) malloc (res->peb_size * sizeof(uint8_t));
+       if (res->buf == NULL) {
+               rc = -ENOMEM;
+               goto ubigen_create_err;
+       }
+
+       /* point to distinct regions within the buffer */
+       res->ptr_ec_hdr = res->buf;
+       res->ptr_vid_hdr = res->buf + __be32_to_cpu(res->ec->vid_hdr_offset);
+       res->ptr_data = res->buf + __be32_to_cpu(res->ec->vid_hdr_offset)
+               + UBI_VID_HDR_SIZE;
+
+       rc = validate_ubi_info(res);
+       if (rc != 0) {
+               fprintf(stderr, "Volume validation failed: %d\n", rc);
+               goto ubigen_create_err;
+       }
+
+       dump_info(res);
+       *u = res;
+       return rc;
+
+ubigen_create_err:
+       if (res) {
+               if (res->v)
+                       free(res->v);
+               if (res->ec)
+                       free(res->ec);
+               if (res->buf)
+                       free(res->buf);
+               free(res);
+       }
+       *u = NULL;
+       return rc;
+}
+
+int
+ubigen_get_leb_size(ubi_info_t u, size_t* size)
+{
+       if (u == NULL)
+               return -EINVAL;
+
+       *size = u->leb_size;
+       return 0;
+}
+
+
+int
+ubigen_get_leb_total(ubi_info_t u, size_t* total)
+{
+       if (u == NULL)
+               return -EINVAL;
+
+       *total = u->leb_total;
+       return 0;
+}
+
+int
+ubigen_set_lvol_rec(ubi_info_t u, size_t reserved_bytes,
+                   const char* vol_name, struct ubi_vtbl_record *lvol_rec)
+{
+       uint32_t crc;
+
+       if ((u == NULL) || (vol_name == NULL))
+               return -EINVAL;
+
+       memset(lvol_rec, 0x0, UBI_VTBL_RECORD_SIZE);
+
+       lvol_rec->reserved_pebs =
+               __cpu_to_be32(byte_to_blk(reserved_bytes, u->leb_size));
+       lvol_rec->alignment = __cpu_to_be32(u->alignment);
+       lvol_rec->data_pad = u->v->data_pad;
+       lvol_rec->vol_type = u->v->vol_type;
+
+       lvol_rec->name_len =
+               __cpu_to_be16((uint16_t)strlen((const char*)vol_name));
+
+       memcpy(lvol_rec->name, vol_name, UBI_VOL_NAME_MAX + 1);
+
+       crc = clc_crc32(crc32_table, UBI_CRC32_INIT,
+                       lvol_rec, UBI_VTBL_RECORD_SIZE_CRC);
+       lvol_rec->crc =  __cpu_to_be32(crc);
+
+       return 0;
+}
index 3b1fc0e095a14f8bdb2ca27cbd33614cb85a22ec..35fad27462823ead9a98a77fd0478dc0a060cbca 100644 (file)
@@ -166,6 +166,7 @@ static int parse_opt(int argc, char * const argv[])
                                }
                                args.peb_size *= mult;
                        }
+                       break;
 
                case 'm':
                        args.min_io_size = strtoull(optarg, &endp, 0);
@@ -183,6 +184,7 @@ static int parse_opt(int argc, char * const argv[])
                                }
                                args.min_io_size *= mult;
                        }
+                       break;
 
                case 'e':
                        args.ec = strtoul(optarg, &endp, 0);
@@ -220,7 +222,7 @@ static int parse_opt(int argc, char * const argv[])
                        break;
 
                case 'O':
-                       args.vid_hdr_offs =  strtoul(optarg, &endp, 0);
+                       args.vid_hdr_offs = strtoul(optarg, &endp, 0);
                        if (endp == optarg || args.vid_hdr_offs < 0) {
                                errmsg("bad VID header offset: \"%s\"", optarg);
                                return -1;