Commit 5af210c2ed5bc38e2d059d512ca4e46e81221af5

Authored by Wolfgang Denk

Merge branch 'master' of git://git.denx.de/u-boot-ubi

Showing 1 changed file Inline Diff

1 /* 1 /*
2 * Unsorted Block Image commands 2 * Unsorted Block Image commands
3 * 3 *
4 * Copyright (C) 2008 Samsung Electronics 4 * Copyright (C) 2008 Samsung Electronics
5 * Kyungmin Park <kyungmin.park@samsung.com> 5 * Kyungmin Park <kyungmin.park@samsung.com>
6 * 6 *
7 * Copyright 2008-2009 Stefan Roese <sr@denx.de>, DENX Software Engineering 7 * Copyright 2008-2009 Stefan Roese <sr@denx.de>, DENX Software Engineering
8 * 8 *
9 * This program is free software; you can redistribute it and/or modify 9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as 10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation. 11 * published by the Free Software Foundation.
12 */ 12 */
13 13
14 #include <common.h> 14 #include <common.h>
15 #include <command.h> 15 #include <command.h>
16 #include <exports.h> 16 #include <exports.h>
17 17
18 #include <nand.h> 18 #include <nand.h>
19 #include <onenand_uboot.h> 19 #include <onenand_uboot.h>
20 #include <linux/mtd/mtd.h> 20 #include <linux/mtd/mtd.h>
21 #include <linux/mtd/partitions.h> 21 #include <linux/mtd/partitions.h>
22 #include <ubi_uboot.h> 22 #include <ubi_uboot.h>
23 #include <asm/errno.h> 23 #include <asm/errno.h>
24 #include <jffs2/load_kernel.h> 24 #include <jffs2/load_kernel.h>
25 25
26 #define DEV_TYPE_NONE 0 26 #define DEV_TYPE_NONE 0
27 #define DEV_TYPE_NAND 1 27 #define DEV_TYPE_NAND 1
28 #define DEV_TYPE_ONENAND 2 28 #define DEV_TYPE_ONENAND 2
29 #define DEV_TYPE_NOR 3 29 #define DEV_TYPE_NOR 3
30 30
31 /* Private own data */ 31 /* Private own data */
32 static struct ubi_device *ubi; 32 static struct ubi_device *ubi;
33 static char buffer[80]; 33 static char buffer[80];
34 static int ubi_initialized; 34 static int ubi_initialized;
35 35
36 struct selected_dev { 36 struct selected_dev {
37 char part_name[80]; 37 char part_name[80];
38 int selected; 38 int selected;
39 int nr; 39 int nr;
40 struct mtd_info *mtd_info; 40 struct mtd_info *mtd_info;
41 }; 41 };
42 42
43 static struct selected_dev ubi_dev; 43 static struct selected_dev ubi_dev;
44 44
45 static void ubi_dump_vol_info(const struct ubi_volume *vol) 45 static void ubi_dump_vol_info(const struct ubi_volume *vol)
46 { 46 {
47 ubi_msg("volume information dump:"); 47 ubi_msg("volume information dump:");
48 ubi_msg("vol_id %d", vol->vol_id); 48 ubi_msg("vol_id %d", vol->vol_id);
49 ubi_msg("reserved_pebs %d", vol->reserved_pebs); 49 ubi_msg("reserved_pebs %d", vol->reserved_pebs);
50 ubi_msg("alignment %d", vol->alignment); 50 ubi_msg("alignment %d", vol->alignment);
51 ubi_msg("data_pad %d", vol->data_pad); 51 ubi_msg("data_pad %d", vol->data_pad);
52 ubi_msg("vol_type %d", vol->vol_type); 52 ubi_msg("vol_type %d", vol->vol_type);
53 ubi_msg("name_len %d", vol->name_len); 53 ubi_msg("name_len %d", vol->name_len);
54 ubi_msg("usable_leb_size %d", vol->usable_leb_size); 54 ubi_msg("usable_leb_size %d", vol->usable_leb_size);
55 ubi_msg("used_ebs %d", vol->used_ebs); 55 ubi_msg("used_ebs %d", vol->used_ebs);
56 ubi_msg("used_bytes %lld", vol->used_bytes); 56 ubi_msg("used_bytes %lld", vol->used_bytes);
57 ubi_msg("last_eb_bytes %d", vol->last_eb_bytes); 57 ubi_msg("last_eb_bytes %d", vol->last_eb_bytes);
58 ubi_msg("corrupted %d", vol->corrupted); 58 ubi_msg("corrupted %d", vol->corrupted);
59 ubi_msg("upd_marker %d", vol->upd_marker); 59 ubi_msg("upd_marker %d", vol->upd_marker);
60 60
61 if (vol->name_len <= UBI_VOL_NAME_MAX && 61 if (vol->name_len <= UBI_VOL_NAME_MAX &&
62 strnlen(vol->name, vol->name_len + 1) == vol->name_len) { 62 strnlen(vol->name, vol->name_len + 1) == vol->name_len) {
63 ubi_msg("name %s", vol->name); 63 ubi_msg("name %s", vol->name);
64 } else { 64 } else {
65 ubi_msg("the 1st 5 characters of the name: %c%c%c%c%c", 65 ubi_msg("the 1st 5 characters of the name: %c%c%c%c%c",
66 vol->name[0], vol->name[1], vol->name[2], 66 vol->name[0], vol->name[1], vol->name[2],
67 vol->name[3], vol->name[4]); 67 vol->name[3], vol->name[4]);
68 } 68 }
69 printf("\n"); 69 printf("\n");
70 } 70 }
71 71
72 static void display_volume_info(struct ubi_device *ubi) 72 static void display_volume_info(struct ubi_device *ubi)
73 { 73 {
74 int i; 74 int i;
75 75
76 for (i = 0; i < (ubi->vtbl_slots + 1); i++) { 76 for (i = 0; i < (ubi->vtbl_slots + 1); i++) {
77 if (!ubi->volumes[i]) 77 if (!ubi->volumes[i])
78 continue; /* Empty record */ 78 continue; /* Empty record */
79 ubi_dump_vol_info(ubi->volumes[i]); 79 ubi_dump_vol_info(ubi->volumes[i]);
80 } 80 }
81 } 81 }
82 82
83 static void display_ubi_info(struct ubi_device *ubi) 83 static void display_ubi_info(struct ubi_device *ubi)
84 { 84 {
85 ubi_msg("MTD device name: \"%s\"", ubi->mtd->name); 85 ubi_msg("MTD device name: \"%s\"", ubi->mtd->name);
86 ubi_msg("MTD device size: %llu MiB", ubi->flash_size >> 20); 86 ubi_msg("MTD device size: %llu MiB", ubi->flash_size >> 20);
87 ubi_msg("physical eraseblock size: %d bytes (%d KiB)", 87 ubi_msg("physical eraseblock size: %d bytes (%d KiB)",
88 ubi->peb_size, ubi->peb_size >> 10); 88 ubi->peb_size, ubi->peb_size >> 10);
89 ubi_msg("logical eraseblock size: %d bytes", ubi->leb_size); 89 ubi_msg("logical eraseblock size: %d bytes", ubi->leb_size);
90 ubi_msg("number of good PEBs: %d", ubi->good_peb_count); 90 ubi_msg("number of good PEBs: %d", ubi->good_peb_count);
91 ubi_msg("number of bad PEBs: %d", ubi->bad_peb_count); 91 ubi_msg("number of bad PEBs: %d", ubi->bad_peb_count);
92 ubi_msg("smallest flash I/O unit: %d", ubi->min_io_size); 92 ubi_msg("smallest flash I/O unit: %d", ubi->min_io_size);
93 ubi_msg("VID header offset: %d (aligned %d)", 93 ubi_msg("VID header offset: %d (aligned %d)",
94 ubi->vid_hdr_offset, ubi->vid_hdr_aloffset); 94 ubi->vid_hdr_offset, ubi->vid_hdr_aloffset);
95 ubi_msg("data offset: %d", ubi->leb_start); 95 ubi_msg("data offset: %d", ubi->leb_start);
96 ubi_msg("max. allowed volumes: %d", ubi->vtbl_slots); 96 ubi_msg("max. allowed volumes: %d", ubi->vtbl_slots);
97 ubi_msg("wear-leveling threshold: %d", CONFIG_MTD_UBI_WL_THRESHOLD); 97 ubi_msg("wear-leveling threshold: %d", CONFIG_MTD_UBI_WL_THRESHOLD);
98 ubi_msg("number of internal volumes: %d", UBI_INT_VOL_COUNT); 98 ubi_msg("number of internal volumes: %d", UBI_INT_VOL_COUNT);
99 ubi_msg("number of user volumes: %d", 99 ubi_msg("number of user volumes: %d",
100 ubi->vol_count - UBI_INT_VOL_COUNT); 100 ubi->vol_count - UBI_INT_VOL_COUNT);
101 ubi_msg("available PEBs: %d", ubi->avail_pebs); 101 ubi_msg("available PEBs: %d", ubi->avail_pebs);
102 ubi_msg("total number of reserved PEBs: %d", ubi->rsvd_pebs); 102 ubi_msg("total number of reserved PEBs: %d", ubi->rsvd_pebs);
103 ubi_msg("number of PEBs reserved for bad PEB handling: %d", 103 ubi_msg("number of PEBs reserved for bad PEB handling: %d",
104 ubi->beb_rsvd_pebs); 104 ubi->beb_rsvd_pebs);
105 ubi_msg("max/mean erase counter: %d/%d", ubi->max_ec, ubi->mean_ec); 105 ubi_msg("max/mean erase counter: %d/%d", ubi->max_ec, ubi->mean_ec);
106 } 106 }
107 107
108 static int ubi_info(int layout) 108 static int ubi_info(int layout)
109 { 109 {
110 if (layout) 110 if (layout)
111 display_volume_info(ubi); 111 display_volume_info(ubi);
112 else 112 else
113 display_ubi_info(ubi); 113 display_ubi_info(ubi);
114 114
115 return 0; 115 return 0;
116 } 116 }
117 117
118 static int verify_mkvol_req(const struct ubi_device *ubi, 118 static int verify_mkvol_req(const struct ubi_device *ubi,
119 const struct ubi_mkvol_req *req) 119 const struct ubi_mkvol_req *req)
120 { 120 {
121 int n, err = -EINVAL; 121 int n, err = -EINVAL;
122 122
123 if (req->bytes < 0 || req->alignment < 0 || req->vol_type < 0 || 123 if (req->bytes < 0 || req->alignment < 0 || req->vol_type < 0 ||
124 req->name_len < 0) 124 req->name_len < 0)
125 goto bad; 125 goto bad;
126 126
127 if ((req->vol_id < 0 || req->vol_id >= ubi->vtbl_slots) && 127 if ((req->vol_id < 0 || req->vol_id >= ubi->vtbl_slots) &&
128 req->vol_id != UBI_VOL_NUM_AUTO) 128 req->vol_id != UBI_VOL_NUM_AUTO)
129 goto bad; 129 goto bad;
130 130
131 if (req->alignment == 0) 131 if (req->alignment == 0)
132 goto bad; 132 goto bad;
133 133
134 if (req->bytes == 0) 134 if (req->bytes == 0)
135 goto bad; 135 goto bad;
136 136
137 if (req->vol_type != UBI_DYNAMIC_VOLUME && 137 if (req->vol_type != UBI_DYNAMIC_VOLUME &&
138 req->vol_type != UBI_STATIC_VOLUME) 138 req->vol_type != UBI_STATIC_VOLUME)
139 goto bad; 139 goto bad;
140 140
141 if (req->alignment > ubi->leb_size) 141 if (req->alignment > ubi->leb_size)
142 goto bad; 142 goto bad;
143 143
144 n = req->alignment % ubi->min_io_size; 144 n = req->alignment % ubi->min_io_size;
145 if (req->alignment != 1 && n) 145 if (req->alignment != 1 && n)
146 goto bad; 146 goto bad;
147 147
148 if (req->name_len > UBI_VOL_NAME_MAX) { 148 if (req->name_len > UBI_VOL_NAME_MAX) {
149 err = -ENAMETOOLONG; 149 err = -ENAMETOOLONG;
150 goto bad; 150 goto bad;
151 } 151 }
152 152
153 return 0; 153 return 0;
154 bad: 154 bad:
155 printf("bad volume creation request"); 155 printf("bad volume creation request");
156 return err; 156 return err;
157 } 157 }
158 158
159 static int ubi_create_vol(char *volume, int size, int dynamic) 159 static int ubi_create_vol(char *volume, int size, int dynamic)
160 { 160 {
161 struct ubi_mkvol_req req; 161 struct ubi_mkvol_req req;
162 int err; 162 int err;
163 163
164 if (dynamic) 164 if (dynamic)
165 req.vol_type = UBI_DYNAMIC_VOLUME; 165 req.vol_type = UBI_DYNAMIC_VOLUME;
166 else 166 else
167 req.vol_type = UBI_STATIC_VOLUME; 167 req.vol_type = UBI_STATIC_VOLUME;
168 168
169 req.vol_id = UBI_VOL_NUM_AUTO; 169 req.vol_id = UBI_VOL_NUM_AUTO;
170 req.alignment = 1; 170 req.alignment = 1;
171 req.bytes = size; 171 req.bytes = size;
172 172
173 strcpy(req.name, volume); 173 strcpy(req.name, volume);
174 req.name_len = strlen(volume); 174 req.name_len = strlen(volume);
175 req.name[req.name_len] = '\0'; 175 req.name[req.name_len] = '\0';
176 req.padding1 = 0; 176 req.padding1 = 0;
177 /* It's duplicated at drivers/mtd/ubi/cdev.c */ 177 /* It's duplicated at drivers/mtd/ubi/cdev.c */
178 err = verify_mkvol_req(ubi, &req); 178 err = verify_mkvol_req(ubi, &req);
179 if (err) { 179 if (err) {
180 printf("verify_mkvol_req failed %d\n", err); 180 printf("verify_mkvol_req failed %d\n", err);
181 return err; 181 return err;
182 } 182 }
183 printf("Creating %s volume %s of size %d\n", 183 printf("Creating %s volume %s of size %d\n",
184 dynamic ? "dynamic" : "static", volume, size); 184 dynamic ? "dynamic" : "static", volume, size);
185 /* Call real ubi create volume */ 185 /* Call real ubi create volume */
186 return ubi_create_volume(ubi, &req); 186 return ubi_create_volume(ubi, &req);
187 } 187 }
188 188
189 static int ubi_remove_vol(char *volume) 189 static int ubi_remove_vol(char *volume)
190 { 190 {
191 int i, err, reserved_pebs; 191 int i, err, reserved_pebs;
192 int found = 0, vol_id = 0; 192 int found = 0, vol_id = 0;
193 struct ubi_volume *vol; 193 struct ubi_volume *vol;
194 194
195 for (i = 0; i < ubi->vtbl_slots; i++) { 195 for (i = 0; i < ubi->vtbl_slots; i++) {
196 vol = ubi->volumes[i]; 196 vol = ubi->volumes[i];
197 if (vol && !strcmp(vol->name, volume)) { 197 if (vol && !strcmp(vol->name, volume)) {
198 printf("Volume %s found at valid %d\n", volume, i); 198 printf("Volume %s found at valid %d\n", volume, i);
199 vol_id = i; 199 vol_id = i;
200 found = 1; 200 found = 1;
201 break; 201 break;
202 } 202 }
203 } 203 }
204 if (!found) { 204 if (!found) {
205 printf("%s volume not found\n", volume); 205 printf("%s volume not found\n", volume);
206 return -ENODEV; 206 return -ENODEV;
207 } 207 }
208 printf("remove UBI volume %s (id %d)\n", vol->name, vol->vol_id); 208 printf("remove UBI volume %s (id %d)\n", vol->name, vol->vol_id);
209 209
210 if (ubi->ro_mode) { 210 if (ubi->ro_mode) {
211 printf("It's read-only mode\n"); 211 printf("It's read-only mode\n");
212 err = -EROFS; 212 err = -EROFS;
213 goto out_err; 213 goto out_err;
214 } 214 }
215 215
216 err = ubi_change_vtbl_record(ubi, vol_id, NULL); 216 err = ubi_change_vtbl_record(ubi, vol_id, NULL);
217 if (err) { 217 if (err) {
218 printf("Error changing Vol tabel record err=%x\n", err); 218 printf("Error changing Vol tabel record err=%x\n", err);
219 goto out_err; 219 goto out_err;
220 } 220 }
221 reserved_pebs = vol->reserved_pebs; 221 reserved_pebs = vol->reserved_pebs;
222 for (i = 0; i < vol->reserved_pebs; i++) { 222 for (i = 0; i < vol->reserved_pebs; i++) {
223 err = ubi_eba_unmap_leb(ubi, vol, i); 223 err = ubi_eba_unmap_leb(ubi, vol, i);
224 if (err) 224 if (err)
225 goto out_err; 225 goto out_err;
226 } 226 }
227 227
228 kfree(vol->eba_tbl); 228 kfree(vol->eba_tbl);
229 ubi->volumes[vol_id]->eba_tbl = NULL; 229 ubi->volumes[vol_id]->eba_tbl = NULL;
230 ubi->volumes[vol_id] = NULL; 230 ubi->volumes[vol_id] = NULL;
231 231
232 ubi->rsvd_pebs -= reserved_pebs; 232 ubi->rsvd_pebs -= reserved_pebs;
233 ubi->avail_pebs += reserved_pebs; 233 ubi->avail_pebs += reserved_pebs;
234 i = ubi->beb_rsvd_level - ubi->beb_rsvd_pebs; 234 i = ubi->beb_rsvd_level - ubi->beb_rsvd_pebs;
235 if (i > 0) { 235 if (i > 0) {
236 i = ubi->avail_pebs >= i ? i : ubi->avail_pebs; 236 i = ubi->avail_pebs >= i ? i : ubi->avail_pebs;
237 ubi->avail_pebs -= i; 237 ubi->avail_pebs -= i;
238 ubi->rsvd_pebs += i; 238 ubi->rsvd_pebs += i;
239 ubi->beb_rsvd_pebs += i; 239 ubi->beb_rsvd_pebs += i;
240 if (i > 0) 240 if (i > 0)
241 ubi_msg("reserve more %d PEBs", i); 241 ubi_msg("reserve more %d PEBs", i);
242 } 242 }
243 ubi->vol_count -= 1; 243 ubi->vol_count -= 1;
244 244
245 return 0; 245 return 0;
246 out_err: 246 out_err:
247 ubi_err("cannot remove volume %d, error %d", vol_id, err); 247 ubi_err("cannot remove volume %d, error %d", vol_id, err);
248 return err; 248 return err;
249 } 249 }
250 250
251 static int ubi_volume_write(char *volume, void *buf, size_t size) 251 static int ubi_volume_write(char *volume, void *buf, size_t size)
252 { 252 {
253 int i = 0, err = -1; 253 int i = 0, err = -1;
254 int rsvd_bytes = 0; 254 int rsvd_bytes = 0;
255 int found = 0; 255 int found = 0;
256 struct ubi_volume *vol; 256 struct ubi_volume *vol;
257 257
258 for (i = 0; i < ubi->vtbl_slots; i++) { 258 for (i = 0; i < ubi->vtbl_slots; i++) {
259 vol = ubi->volumes[i]; 259 vol = ubi->volumes[i];
260 if (vol && !strcmp(vol->name, volume)) { 260 if (vol && !strcmp(vol->name, volume)) {
261 printf("Volume \"%s\" found at volume id %d\n", volume, i); 261 printf("Volume \"%s\" found at volume id %d\n", volume, i);
262 found = 1; 262 found = 1;
263 break; 263 break;
264 } 264 }
265 } 265 }
266 if (!found) { 266 if (!found) {
267 printf("%s volume not found\n", volume); 267 printf("%s volume not found\n", volume);
268 return 1; 268 return 1;
269 } 269 }
270 rsvd_bytes = vol->reserved_pebs * (ubi->leb_size - vol->data_pad); 270 rsvd_bytes = vol->reserved_pebs * (ubi->leb_size - vol->data_pad);
271 if (size < 0 || size > rsvd_bytes) { 271 if (size < 0 || size > rsvd_bytes) {
272 printf("rsvd_bytes=%d vol->reserved_pebs=%d ubi->leb_size=%d\n", 272 printf("rsvd_bytes=%d vol->reserved_pebs=%d ubi->leb_size=%d\n",
273 rsvd_bytes, vol->reserved_pebs, ubi->leb_size); 273 rsvd_bytes, vol->reserved_pebs, ubi->leb_size);
274 printf("vol->data_pad=%d\n", vol->data_pad); 274 printf("vol->data_pad=%d\n", vol->data_pad);
275 printf("Size > volume size !!\n"); 275 printf("Size > volume size !!\n");
276 return 1; 276 return 1;
277 } 277 }
278 278
279 err = ubi_start_update(ubi, vol, size); 279 err = ubi_start_update(ubi, vol, size);
280 if (err < 0) { 280 if (err < 0) {
281 printf("Cannot start volume update\n"); 281 printf("Cannot start volume update\n");
282 return err; 282 return err;
283 } 283 }
284 284
285 err = ubi_more_update_data(ubi, vol, buf, size); 285 err = ubi_more_update_data(ubi, vol, buf, size);
286 if (err < 0) { 286 if (err < 0) {
287 printf("Couldnt or partially wrote data \n"); 287 printf("Couldnt or partially wrote data \n");
288 return err; 288 return err;
289 } 289 }
290 290
291 if (err) { 291 if (err) {
292 size = err; 292 size = err;
293 293
294 err = ubi_check_volume(ubi, vol->vol_id); 294 err = ubi_check_volume(ubi, vol->vol_id);
295 if ( err < 0 ) 295 if ( err < 0 )
296 return err; 296 return err;
297 297
298 if (err) { 298 if (err) {
299 ubi_warn("volume %d on UBI device %d is corrupted", 299 ubi_warn("volume %d on UBI device %d is corrupted",
300 vol->vol_id, ubi->ubi_num); 300 vol->vol_id, ubi->ubi_num);
301 vol->corrupted = 1; 301 vol->corrupted = 1;
302 } 302 }
303 303
304 vol->checked = 1; 304 vol->checked = 1;
305 ubi_gluebi_updated(vol); 305 ubi_gluebi_updated(vol);
306 } 306 }
307 307
308 return 0; 308 return 0;
309 } 309 }
310 310
311 static int ubi_volume_read(char *volume, char *buf, size_t size) 311 static int ubi_volume_read(char *volume, char *buf, size_t size)
312 { 312 {
313 int err, lnum, off, len, tbuf_size, i = 0; 313 int err, lnum, off, len, tbuf_size, i = 0;
314 size_t count_save = size; 314 size_t count_save = size;
315 void *tbuf; 315 void *tbuf;
316 unsigned long long tmp; 316 unsigned long long tmp;
317 struct ubi_volume *vol = NULL; 317 struct ubi_volume *vol = NULL;
318 loff_t offp = 0; 318 loff_t offp = 0;
319 319
320 for (i = 0; i < ubi->vtbl_slots; i++) { 320 for (i = 0; i < ubi->vtbl_slots; i++) {
321 vol = ubi->volumes[i]; 321 vol = ubi->volumes[i];
322 if (vol && !strcmp(vol->name, volume)) { 322 if (vol && !strcmp(vol->name, volume)) {
323 printf("Volume %s found at volume id %d\n", 323 printf("Volume %s found at volume id %d\n",
324 volume, vol->vol_id); 324 volume, vol->vol_id);
325 break; 325 break;
326 } 326 }
327 } 327 }
328 if (i == ubi->vtbl_slots) { 328 if (i == ubi->vtbl_slots) {
329 printf("%s volume not found\n", volume); 329 printf("%s volume not found\n", volume);
330 return 0; 330 return -ENODEV;
331 } 331 }
332 332
333 printf("read %i bytes from volume %d to %x(buf address)\n", 333 printf("read %i bytes from volume %d to %x(buf address)\n",
334 (int) size, vol->vol_id, (unsigned)buf); 334 (int) size, vol->vol_id, (unsigned)buf);
335 335
336 if (vol->updating) { 336 if (vol->updating) {
337 printf("updating"); 337 printf("updating");
338 return -EBUSY; 338 return -EBUSY;
339 } 339 }
340 if (vol->upd_marker) { 340 if (vol->upd_marker) {
341 printf("damaged volume, update marker is set"); 341 printf("damaged volume, update marker is set");
342 return -EBADF; 342 return -EBADF;
343 } 343 }
344 if (offp == vol->used_bytes) 344 if (offp == vol->used_bytes)
345 return 0; 345 return 0;
346 346
347 if (size == 0) { 347 if (size == 0) {
348 printf("Read [%lu] bytes\n", (unsigned long) vol->used_bytes); 348 printf("Read [%lu] bytes\n", (unsigned long) vol->used_bytes);
349 size = vol->used_bytes; 349 size = vol->used_bytes;
350 } 350 }
351 351
352 if (vol->corrupted) 352 if (vol->corrupted)
353 printf("read from corrupted volume %d", vol->vol_id); 353 printf("read from corrupted volume %d", vol->vol_id);
354 if (offp + size > vol->used_bytes) 354 if (offp + size > vol->used_bytes)
355 count_save = size = vol->used_bytes - offp; 355 count_save = size = vol->used_bytes - offp;
356 356
357 tbuf_size = vol->usable_leb_size; 357 tbuf_size = vol->usable_leb_size;
358 if (size < tbuf_size) 358 if (size < tbuf_size)
359 tbuf_size = ALIGN(size, ubi->min_io_size); 359 tbuf_size = ALIGN(size, ubi->min_io_size);
360 tbuf = malloc(tbuf_size); 360 tbuf = malloc(tbuf_size);
361 if (!tbuf) { 361 if (!tbuf) {
362 printf("NO MEM\n"); 362 printf("NO MEM\n");
363 return -ENOMEM; 363 return -ENOMEM;
364 } 364 }
365 len = size > tbuf_size ? tbuf_size : size; 365 len = size > tbuf_size ? tbuf_size : size;
366 366
367 tmp = offp; 367 tmp = offp;
368 off = do_div(tmp, vol->usable_leb_size); 368 off = do_div(tmp, vol->usable_leb_size);
369 lnum = tmp; 369 lnum = tmp;
370 do { 370 do {
371 if (off + len >= vol->usable_leb_size) 371 if (off + len >= vol->usable_leb_size)
372 len = vol->usable_leb_size - off; 372 len = vol->usable_leb_size - off;
373 373
374 err = ubi_eba_read_leb(ubi, vol, lnum, tbuf, off, len, 0); 374 err = ubi_eba_read_leb(ubi, vol, lnum, tbuf, off, len, 0);
375 if (err) { 375 if (err) {
376 printf("read err %x\n", err); 376 printf("read err %x\n", err);
377 break; 377 break;
378 } 378 }
379 off += len; 379 off += len;
380 if (off == vol->usable_leb_size) { 380 if (off == vol->usable_leb_size) {
381 lnum += 1; 381 lnum += 1;
382 off -= vol->usable_leb_size; 382 off -= vol->usable_leb_size;
383 } 383 }
384 384
385 size -= len; 385 size -= len;
386 offp += len; 386 offp += len;
387 387
388 memcpy(buf, tbuf, len); 388 memcpy(buf, tbuf, len);
389 389
390 buf += len; 390 buf += len;
391 len = size > tbuf_size ? tbuf_size : size; 391 len = size > tbuf_size ? tbuf_size : size;
392 } while (size); 392 } while (size);
393 393
394 free(tbuf); 394 free(tbuf);
395 return err ? err : count_save - size; 395 return err ? err : count_save - size;
396 } 396 }
397 397
398 static int ubi_dev_scan(struct mtd_info *info, char *ubidev) 398 static int ubi_dev_scan(struct mtd_info *info, char *ubidev)
399 { 399 {
400 struct mtd_device *dev; 400 struct mtd_device *dev;
401 struct part_info *part; 401 struct part_info *part;
402 struct mtd_partition mtd_part; 402 struct mtd_partition mtd_part;
403 u8 pnum; 403 u8 pnum;
404 int err; 404 int err;
405 405
406 if (find_dev_and_part(ubidev, &dev, &pnum, &part) != 0) 406 if (find_dev_and_part(ubidev, &dev, &pnum, &part) != 0)
407 return 1; 407 return 1;
408 408
409 sprintf(buffer, "mtd=%d", pnum); 409 sprintf(buffer, "mtd=%d", pnum);
410 memset(&mtd_part, 0, sizeof(mtd_part)); 410 memset(&mtd_part, 0, sizeof(mtd_part));
411 mtd_part.name = buffer; 411 mtd_part.name = buffer;
412 mtd_part.size = part->size; 412 mtd_part.size = part->size;
413 mtd_part.offset = part->offset; 413 mtd_part.offset = part->offset;
414 add_mtd_partitions(info, &mtd_part, 1); 414 add_mtd_partitions(info, &mtd_part, 1);
415 415
416 err = ubi_mtd_param_parse(buffer, NULL); 416 err = ubi_mtd_param_parse(buffer, NULL);
417 if (err) { 417 if (err) {
418 del_mtd_partitions(info); 418 del_mtd_partitions(info);
419 return err; 419 return err;
420 } 420 }
421 421
422 err = ubi_init(); 422 err = ubi_init();
423 if (err) { 423 if (err) {
424 del_mtd_partitions(info); 424 del_mtd_partitions(info);
425 return err; 425 return err;
426 } 426 }
427 427
428 ubi_initialized = 1; 428 ubi_initialized = 1;
429 429
430 return 0; 430 return 0;
431 } 431 }
432 432
433 static int do_ubi(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) 433 static int do_ubi(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
434 { 434 {
435 size_t size = 0; 435 size_t size = 0;
436 ulong addr = 0; 436 ulong addr = 0;
437 int err = 0; 437 int err = 0;
438 438
439 if (argc < 2) { 439 if (argc < 2) {
440 cmd_usage(cmdtp); 440 cmd_usage(cmdtp);
441 return 1; 441 return 1;
442 } 442 }
443 443
444 if (mtdparts_init() != 0) { 444 if (mtdparts_init() != 0) {
445 printf("Error initializing mtdparts!\n"); 445 printf("Error initializing mtdparts!\n");
446 return 1; 446 return 1;
447 } 447 }
448 448
449 if (strcmp(argv[1], "part") == 0) { 449 if (strcmp(argv[1], "part") == 0) {
450 char mtd_dev[16]; 450 char mtd_dev[16];
451 struct mtd_device *dev; 451 struct mtd_device *dev;
452 struct part_info *part; 452 struct part_info *part;
453 u8 pnum; 453 u8 pnum;
454 454
455 /* Print current partition */ 455 /* Print current partition */
456 if (argc == 2) { 456 if (argc == 2) {
457 if (!ubi_dev.selected) { 457 if (!ubi_dev.selected) {
458 printf("Error, no UBI device/partition selected!\n"); 458 printf("Error, no UBI device/partition selected!\n");
459 return 1; 459 return 1;
460 } 460 }
461 461
462 printf("Device %d: %s, partition %s\n", 462 printf("Device %d: %s, partition %s\n",
463 ubi_dev.nr, ubi_dev.mtd_info->name, ubi_dev.part_name); 463 ubi_dev.nr, ubi_dev.mtd_info->name, ubi_dev.part_name);
464 return 0; 464 return 0;
465 } 465 }
466 466
467 if (argc < 3) { 467 if (argc < 3) {
468 cmd_usage(cmdtp); 468 cmd_usage(cmdtp);
469 return 1; 469 return 1;
470 } 470 }
471 471
472 /* todo: get dev number for NAND... */ 472 /* todo: get dev number for NAND... */
473 ubi_dev.nr = 0; 473 ubi_dev.nr = 0;
474 474
475 /* 475 /*
476 * Call ubi_exit() before re-initializing the UBI subsystem 476 * Call ubi_exit() before re-initializing the UBI subsystem
477 */ 477 */
478 if (ubi_initialized) { 478 if (ubi_initialized) {
479 ubi_exit(); 479 ubi_exit();
480 del_mtd_partitions(ubi_dev.mtd_info); 480 del_mtd_partitions(ubi_dev.mtd_info);
481 } 481 }
482 482
483 /* 483 /*
484 * Search the mtd device number where this partition 484 * Search the mtd device number where this partition
485 * is located 485 * is located
486 */ 486 */
487 if (find_dev_and_part(argv[2], &dev, &pnum, &part)) { 487 if (find_dev_and_part(argv[2], &dev, &pnum, &part)) {
488 printf("Partition %s not found!\n", argv[2]); 488 printf("Partition %s not found!\n", argv[2]);
489 return 1; 489 return 1;
490 } 490 }
491 sprintf(mtd_dev, "%s%d", MTD_DEV_TYPE(dev->id->type), dev->id->num); 491 sprintf(mtd_dev, "%s%d", MTD_DEV_TYPE(dev->id->type), dev->id->num);
492 ubi_dev.mtd_info = get_mtd_device_nm(mtd_dev); 492 ubi_dev.mtd_info = get_mtd_device_nm(mtd_dev);
493 if (IS_ERR(ubi_dev.mtd_info)) { 493 if (IS_ERR(ubi_dev.mtd_info)) {
494 printf("Partition %s not found on device %s!\n", argv[2], mtd_dev); 494 printf("Partition %s not found on device %s!\n", argv[2], mtd_dev);
495 return 1; 495 return 1;
496 } 496 }
497 497
498 ubi_dev.selected = 1; 498 ubi_dev.selected = 1;
499 499
500 strcpy(ubi_dev.part_name, argv[2]); 500 strcpy(ubi_dev.part_name, argv[2]);
501 err = ubi_dev_scan(ubi_dev.mtd_info, ubi_dev.part_name); 501 err = ubi_dev_scan(ubi_dev.mtd_info, ubi_dev.part_name);
502 if (err) { 502 if (err) {
503 printf("UBI init error %d\n", err); 503 printf("UBI init error %d\n", err);
504 ubi_dev.selected = 0; 504 ubi_dev.selected = 0;
505 return err; 505 return err;
506 } 506 }
507 507
508 ubi = ubi_devices[0]; 508 ubi = ubi_devices[0];
509 509
510 return 0; 510 return 0;
511 } 511 }
512 512
513 if ((strcmp(argv[1], "part") != 0) && (!ubi_dev.selected)) { 513 if ((strcmp(argv[1], "part") != 0) && (!ubi_dev.selected)) {
514 printf("Error, no UBI device/partition selected!\n"); 514 printf("Error, no UBI device/partition selected!\n");
515 return 1; 515 return 1;
516 } 516 }
517 517
518 if (strcmp(argv[1], "info") == 0) { 518 if (strcmp(argv[1], "info") == 0) {
519 int layout = 0; 519 int layout = 0;
520 if (argc > 2 && !strncmp(argv[2], "l", 1)) 520 if (argc > 2 && !strncmp(argv[2], "l", 1))
521 layout = 1; 521 layout = 1;
522 return ubi_info(layout); 522 return ubi_info(layout);
523 } 523 }
524 524
525 if (strncmp(argv[1], "create", 6) == 0) { 525 if (strncmp(argv[1], "create", 6) == 0) {
526 int dynamic = 1; /* default: dynamic volume */ 526 int dynamic = 1; /* default: dynamic volume */
527 527
528 /* Use maximum available size */ 528 /* Use maximum available size */
529 size = 0; 529 size = 0;
530 530
531 /* E.g., create volume size type */ 531 /* E.g., create volume size type */
532 if (argc == 5) { 532 if (argc == 5) {
533 if (strncmp(argv[4], "s", 1) == 0) 533 if (strncmp(argv[4], "s", 1) == 0)
534 dynamic = 0; 534 dynamic = 0;
535 else if (strncmp(argv[4], "d", 1) != 0) { 535 else if (strncmp(argv[4], "d", 1) != 0) {
536 printf("Incorrect type\n"); 536 printf("Incorrect type\n");
537 return 1; 537 return 1;
538 } 538 }
539 argc--; 539 argc--;
540 } 540 }
541 /* E.g., create volume size */ 541 /* E.g., create volume size */
542 if (argc == 4) { 542 if (argc == 4) {
543 size = simple_strtoul(argv[3], NULL, 16); 543 size = simple_strtoul(argv[3], NULL, 16);
544 argc--; 544 argc--;
545 } 545 }
546 /* Use maximum available size */ 546 /* Use maximum available size */
547 if (!size) 547 if (!size)
548 size = ubi->avail_pebs * ubi->leb_size; 548 size = ubi->avail_pebs * ubi->leb_size;
549 /* E.g., create volume */ 549 /* E.g., create volume */
550 if (argc == 3) 550 if (argc == 3)
551 return ubi_create_vol(argv[2], size, dynamic); 551 return ubi_create_vol(argv[2], size, dynamic);
552 } 552 }
553 553
554 if (strncmp(argv[1], "remove", 6) == 0) { 554 if (strncmp(argv[1], "remove", 6) == 0) {
555 /* E.g., remove volume */ 555 /* E.g., remove volume */
556 if (argc == 3) 556 if (argc == 3)
557 return ubi_remove_vol(argv[2]); 557 return ubi_remove_vol(argv[2]);
558 } 558 }
559 559
560 if (strncmp(argv[1], "write", 5) == 0) { 560 if (strncmp(argv[1], "write", 5) == 0) {
561 if (argc < 5) { 561 if (argc < 5) {
562 printf("Please see usage\n"); 562 printf("Please see usage\n");
563 return 1; 563 return 1;
564 } 564 }
565 565
566 addr = simple_strtoul(argv[2], NULL, 16); 566 addr = simple_strtoul(argv[2], NULL, 16);
567 size = simple_strtoul(argv[4], NULL, 16); 567 size = simple_strtoul(argv[4], NULL, 16);
568 568
569 return ubi_volume_write(argv[3], (void *)addr, size); 569 return ubi_volume_write(argv[3], (void *)addr, size);
570 } 570 }
571 571
572 if (strncmp(argv[1], "read", 4) == 0) { 572 if (strncmp(argv[1], "read", 4) == 0) {
573 size = 0; 573 size = 0;
574 574
575 /* E.g., read volume size */ 575 /* E.g., read volume size */
576 if (argc == 5) { 576 if (argc == 5) {
577 size = simple_strtoul(argv[4], NULL, 16); 577 size = simple_strtoul(argv[4], NULL, 16);
578 argc--; 578 argc--;
579 } 579 }
580 580
581 /* E.g., read volume */ 581 /* E.g., read volume */
582 if (argc == 4) { 582 if (argc == 4) {
583 addr = simple_strtoul(argv[2], NULL, 16); 583 addr = simple_strtoul(argv[2], NULL, 16);
584 argc--; 584 argc--;
585 } 585 }
586 586
587 if (argc == 3) 587 if (argc == 3)
588 return ubi_volume_read(argv[3], (char *)addr, size); 588 return ubi_volume_read(argv[3], (char *)addr, size);
589 } 589 }
590 590
591 printf("Please see usage\n"); 591 printf("Please see usage\n");
592 return -1; 592 return -1;
593 } 593 }
594 594
595 U_BOOT_CMD(ubi, 6, 1, do_ubi, 595 U_BOOT_CMD(ubi, 6, 1, do_ubi,
596 "ubi commands", 596 "ubi commands",
597 "part [part]" 597 "part [part]"
598 " - Show or set current partition\n" 598 " - Show or set current partition\n"
599 "ubi info [l[ayout]]" 599 "ubi info [l[ayout]]"
600 " - Display volume and ubi layout information\n" 600 " - Display volume and ubi layout information\n"
601 "ubi create[vol] volume [size] [type]" 601 "ubi create[vol] volume [size] [type]"
602 " - create volume name with size\n" 602 " - create volume name with size\n"
603 "ubi write[vol] address volume size" 603 "ubi write[vol] address volume size"
604 " - Write volume from address with size\n" 604 " - Write volume from address with size\n"
605 "ubi read[vol] address volume [size]" 605 "ubi read[vol] address volume [size]"
606 " - Read volume to address with size\n" 606 " - Read volume to address with size\n"
607 "ubi remove[vol] volume" 607 "ubi remove[vol] volume"
608 " - Remove volume\n" 608 " - Remove volume\n"
609 "[Legends]\n" 609 "[Legends]\n"
610 " volume: charater name\n" 610 " volume: charater name\n"
611 " size: KiB, MiB, GiB, and bytes\n" 611 " size: KiB, MiB, GiB, and bytes\n"
612 " type: s[tatic] or d[ynamic] (default=dynamic)\n" 612 " type: s[tatic] or d[ynamic] (default=dynamic)\n"
613 ); 613 );
614 614