diff options
author | Adrian Hunter <adrian.hunter@nokia.com> | 2009-06-26 07:58:01 -0400 |
---|---|---|
committer | Artem Bityutskiy <Artem.Bityutskiy@nokia.com> | 2009-07-05 11:47:07 -0400 |
commit | 0c6c7fa1313fcb69cae35e34168d2e83b8da854a (patch) | |
tree | 5ba3c6eda144b060829529096f30c6f83e357d5b /drivers/mtd | |
parent | 1398788fe7b730db10e97dcb9f838603e41922d5 (diff) |
UBI: add image sequence number to EC header
An image sequence number is added to the UBI erase-counter header
to be able determine if the root file system contains a mixture
of old and new images (because the flashing failed to complete).
A change to nolo is also needed for this to take effect.
Signed-off-by: Adrian Hunter <adrian.hunter@nokia.com>
Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
Diffstat (limited to 'drivers/mtd')
-rw-r--r-- | drivers/mtd/ubi/build.c | 1 | ||||
-rw-r--r-- | drivers/mtd/ubi/debug.c | 2 | ||||
-rw-r--r-- | drivers/mtd/ubi/io.c | 15 | ||||
-rw-r--r-- | drivers/mtd/ubi/scan.c | 2 | ||||
-rw-r--r-- | drivers/mtd/ubi/ubi-media.h | 12 | ||||
-rw-r--r-- | drivers/mtd/ubi/ubi.h | 4 |
6 files changed, 33 insertions, 3 deletions
diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c index 286ed594e5a0..db0b9cb64c6c 100644 --- a/drivers/mtd/ubi/build.c +++ b/drivers/mtd/ubi/build.c | |||
@@ -996,6 +996,7 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset) | |||
996 | ubi_msg("number of PEBs reserved for bad PEB handling: %d", | 996 | ubi_msg("number of PEBs reserved for bad PEB handling: %d", |
997 | ubi->beb_rsvd_pebs); | 997 | ubi->beb_rsvd_pebs); |
998 | ubi_msg("max/mean erase counter: %d/%d", ubi->max_ec, ubi->mean_ec); | 998 | ubi_msg("max/mean erase counter: %d/%d", ubi->max_ec, ubi->mean_ec); |
999 | ubi_msg("image sequence number: %d", ubi->image_seq); | ||
999 | 1000 | ||
1000 | /* | 1001 | /* |
1001 | * The below lock makes sure we do not race with 'ubi_thread()' which | 1002 | * The below lock makes sure we do not race with 'ubi_thread()' which |
diff --git a/drivers/mtd/ubi/debug.c b/drivers/mtd/ubi/debug.c index c0ed60e8ade9..54b0186915fb 100644 --- a/drivers/mtd/ubi/debug.c +++ b/drivers/mtd/ubi/debug.c | |||
@@ -44,6 +44,8 @@ void ubi_dbg_dump_ec_hdr(const struct ubi_ec_hdr *ec_hdr) | |||
44 | be32_to_cpu(ec_hdr->vid_hdr_offset)); | 44 | be32_to_cpu(ec_hdr->vid_hdr_offset)); |
45 | printk(KERN_DEBUG "\tdata_offset %d\n", | 45 | printk(KERN_DEBUG "\tdata_offset %d\n", |
46 | be32_to_cpu(ec_hdr->data_offset)); | 46 | be32_to_cpu(ec_hdr->data_offset)); |
47 | printk(KERN_DEBUG "\timage_seq %d\n", | ||
48 | be32_to_cpu(ec_hdr->image_seq)); | ||
47 | printk(KERN_DEBUG "\thdr_crc %#08x\n", | 49 | printk(KERN_DEBUG "\thdr_crc %#08x\n", |
48 | be32_to_cpu(ec_hdr->hdr_crc)); | 50 | be32_to_cpu(ec_hdr->hdr_crc)); |
49 | printk(KERN_DEBUG "erase counter header hexdump:\n"); | 51 | printk(KERN_DEBUG "erase counter header hexdump:\n"); |
diff --git a/drivers/mtd/ubi/io.c b/drivers/mtd/ubi/io.c index c8edbfd09b64..b58714011091 100644 --- a/drivers/mtd/ubi/io.c +++ b/drivers/mtd/ubi/io.c | |||
@@ -563,15 +563,16 @@ int ubi_io_mark_bad(const struct ubi_device *ubi, int pnum) | |||
563 | * This function returns zero if the erase counter header is OK, and %1 if | 563 | * This function returns zero if the erase counter header is OK, and %1 if |
564 | * not. | 564 | * not. |
565 | */ | 565 | */ |
566 | static int validate_ec_hdr(const struct ubi_device *ubi, | 566 | static int validate_ec_hdr(struct ubi_device *ubi, |
567 | const struct ubi_ec_hdr *ec_hdr) | 567 | const struct ubi_ec_hdr *ec_hdr) |
568 | { | 568 | { |
569 | long long ec; | 569 | long long ec; |
570 | int vid_hdr_offset, leb_start; | 570 | int vid_hdr_offset, leb_start, image_seq; |
571 | 571 | ||
572 | ec = be64_to_cpu(ec_hdr->ec); | 572 | ec = be64_to_cpu(ec_hdr->ec); |
573 | vid_hdr_offset = be32_to_cpu(ec_hdr->vid_hdr_offset); | 573 | vid_hdr_offset = be32_to_cpu(ec_hdr->vid_hdr_offset); |
574 | leb_start = be32_to_cpu(ec_hdr->data_offset); | 574 | leb_start = be32_to_cpu(ec_hdr->data_offset); |
575 | image_seq = be32_to_cpu(ec_hdr->image_seq); | ||
575 | 576 | ||
576 | if (ec_hdr->version != UBI_VERSION) { | 577 | if (ec_hdr->version != UBI_VERSION) { |
577 | ubi_err("node with incompatible UBI version found: " | 578 | ubi_err("node with incompatible UBI version found: " |
@@ -597,6 +598,15 @@ static int validate_ec_hdr(const struct ubi_device *ubi, | |||
597 | goto bad; | 598 | goto bad; |
598 | } | 599 | } |
599 | 600 | ||
601 | if (!ubi->image_seq_set) { | ||
602 | ubi->image_seq = image_seq; | ||
603 | ubi->image_seq_set = 1; | ||
604 | } else if (ubi->image_seq != image_seq) { | ||
605 | ubi_err("bad image sequence number %d, expected %d", | ||
606 | image_seq, ubi->image_seq); | ||
607 | goto bad; | ||
608 | } | ||
609 | |||
600 | return 0; | 610 | return 0; |
601 | 611 | ||
602 | bad: | 612 | bad: |
@@ -742,6 +752,7 @@ int ubi_io_write_ec_hdr(struct ubi_device *ubi, int pnum, | |||
742 | ec_hdr->version = UBI_VERSION; | 752 | ec_hdr->version = UBI_VERSION; |
743 | ec_hdr->vid_hdr_offset = cpu_to_be32(ubi->vid_hdr_offset); | 753 | ec_hdr->vid_hdr_offset = cpu_to_be32(ubi->vid_hdr_offset); |
744 | ec_hdr->data_offset = cpu_to_be32(ubi->leb_start); | 754 | ec_hdr->data_offset = cpu_to_be32(ubi->leb_start); |
755 | ec_hdr->image_seq = cpu_to_be32(ubi->image_seq); | ||
745 | crc = crc32(UBI_CRC32_INIT, ec_hdr, UBI_EC_HDR_SIZE_CRC); | 756 | crc = crc32(UBI_CRC32_INIT, ec_hdr, UBI_EC_HDR_SIZE_CRC); |
746 | ec_hdr->hdr_crc = cpu_to_be32(crc); | 757 | ec_hdr->hdr_crc = cpu_to_be32(crc); |
747 | 758 | ||
diff --git a/drivers/mtd/ubi/scan.c b/drivers/mtd/ubi/scan.c index c3d653ba5ca0..72570ed7d33f 100644 --- a/drivers/mtd/ubi/scan.c +++ b/drivers/mtd/ubi/scan.c | |||
@@ -910,6 +910,8 @@ struct ubi_scan_info *ubi_scan(struct ubi_device *ubi) | |||
910 | if (si->is_empty) | 910 | if (si->is_empty) |
911 | ubi_msg("empty MTD device detected"); | 911 | ubi_msg("empty MTD device detected"); |
912 | 912 | ||
913 | ubi->image_seq_set = 1; | ||
914 | |||
913 | /* | 915 | /* |
914 | * In case of unknown erase counter we use the mean erase counter | 916 | * In case of unknown erase counter we use the mean erase counter |
915 | * value. | 917 | * value. |
diff --git a/drivers/mtd/ubi/ubi-media.h b/drivers/mtd/ubi/ubi-media.h index 8419fdccc79c..503ea9b27309 100644 --- a/drivers/mtd/ubi/ubi-media.h +++ b/drivers/mtd/ubi/ubi-media.h | |||
@@ -129,6 +129,7 @@ enum { | |||
129 | * @ec: the erase counter | 129 | * @ec: the erase counter |
130 | * @vid_hdr_offset: where the VID header starts | 130 | * @vid_hdr_offset: where the VID header starts |
131 | * @data_offset: where the user data start | 131 | * @data_offset: where the user data start |
132 | * @image_seq: image sequence number | ||
132 | * @padding2: reserved for future, zeroes | 133 | * @padding2: reserved for future, zeroes |
133 | * @hdr_crc: erase counter header CRC checksum | 134 | * @hdr_crc: erase counter header CRC checksum |
134 | * | 135 | * |
@@ -144,6 +145,14 @@ enum { | |||
144 | * volume identifier header and user data, relative to the beginning of the | 145 | * volume identifier header and user data, relative to the beginning of the |
145 | * physical eraseblock. These values have to be the same for all physical | 146 | * physical eraseblock. These values have to be the same for all physical |
146 | * eraseblocks. | 147 | * eraseblocks. |
148 | * | ||
149 | * The @image_seq field is used to validate a UBI image that has been prepared | ||
150 | * for a UBI device. The @image_seq value can be any value, but it must be the | ||
151 | * same on all eraseblocks. UBI will ensure that all new erase counter headers | ||
152 | * also contain this value, and will check the value when scanning at start-up. | ||
153 | * One way to make use of @image_seq is to increase its value by one every time | ||
154 | * an image is flashed over an existing image, then, if the flashing does not | ||
155 | * complete, UBI will detect the error when scanning. | ||
147 | */ | 156 | */ |
148 | struct ubi_ec_hdr { | 157 | struct ubi_ec_hdr { |
149 | __be32 magic; | 158 | __be32 magic; |
@@ -152,7 +161,8 @@ struct ubi_ec_hdr { | |||
152 | __be64 ec; /* Warning: the current limit is 31-bit anyway! */ | 161 | __be64 ec; /* Warning: the current limit is 31-bit anyway! */ |
153 | __be32 vid_hdr_offset; | 162 | __be32 vid_hdr_offset; |
154 | __be32 data_offset; | 163 | __be32 data_offset; |
155 | __u8 padding2[36]; | 164 | __be32 image_seq; |
165 | __u8 padding2[32]; | ||
156 | __be32 hdr_crc; | 166 | __be32 hdr_crc; |
157 | } __attribute__ ((packed)); | 167 | } __attribute__ ((packed)); |
158 | 168 | ||
diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h index 28acd133c997..bb372c4222b7 100644 --- a/drivers/mtd/ubi/ubi.h +++ b/drivers/mtd/ubi/ubi.h | |||
@@ -301,6 +301,8 @@ struct ubi_wl_entry; | |||
301 | * @vol->readers, @vol->writers, @vol->exclusive, | 301 | * @vol->readers, @vol->writers, @vol->exclusive, |
302 | * @vol->ref_count, @vol->mapping and @vol->eba_tbl. | 302 | * @vol->ref_count, @vol->mapping and @vol->eba_tbl. |
303 | * @ref_count: count of references on the UBI device | 303 | * @ref_count: count of references on the UBI device |
304 | * @image_seq: image sequence number recorded on EC headers | ||
305 | * @image_seq_set: indicates @image_seq is known | ||
304 | * | 306 | * |
305 | * @rsvd_pebs: count of reserved physical eraseblocks | 307 | * @rsvd_pebs: count of reserved physical eraseblocks |
306 | * @avail_pebs: count of available physical eraseblocks | 308 | * @avail_pebs: count of available physical eraseblocks |
@@ -390,6 +392,8 @@ struct ubi_device { | |||
390 | struct ubi_volume *volumes[UBI_MAX_VOLUMES+UBI_INT_VOL_COUNT]; | 392 | struct ubi_volume *volumes[UBI_MAX_VOLUMES+UBI_INT_VOL_COUNT]; |
391 | spinlock_t volumes_lock; | 393 | spinlock_t volumes_lock; |
392 | int ref_count; | 394 | int ref_count; |
395 | int image_seq; | ||
396 | int image_seq_set; | ||
393 | 397 | ||
394 | int rsvd_pebs; | 398 | int rsvd_pebs; |
395 | int avail_pebs; | 399 | int avail_pebs; |