1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29#ifndef __UBOOT__
30#include <linux/uaccess.h>
31#else
32#include <div64.h>
33#include <ubi_uboot.h>
34#endif
35#include <linux/err.h>
36#include <linux/math64.h>
37
38#include "ubi.h"
39
40
41
42
43
44
45
46
47
48static int set_update_marker(struct ubi_device *ubi, struct ubi_volume *vol)
49{
50 int err;
51 struct ubi_vtbl_record vtbl_rec;
52
53 dbg_gen("set update marker for volume %d", vol->vol_id);
54
55 if (vol->upd_marker) {
56 ubi_assert(ubi->vtbl[vol->vol_id].upd_marker);
57 dbg_gen("already set");
58 return 0;
59 }
60
61 vtbl_rec = ubi->vtbl[vol->vol_id];
62 vtbl_rec.upd_marker = 1;
63
64 mutex_lock(&ubi->device_mutex);
65 err = ubi_change_vtbl_record(ubi, vol->vol_id, &vtbl_rec);
66 vol->upd_marker = 1;
67 mutex_unlock(&ubi->device_mutex);
68 return err;
69}
70
71
72
73
74
75
76
77
78
79
80
81static int clear_update_marker(struct ubi_device *ubi, struct ubi_volume *vol,
82 long long bytes)
83{
84 int err;
85 struct ubi_vtbl_record vtbl_rec;
86
87 dbg_gen("clear update marker for volume %d", vol->vol_id);
88
89 vtbl_rec = ubi->vtbl[vol->vol_id];
90 ubi_assert(vol->upd_marker && vtbl_rec.upd_marker);
91 vtbl_rec.upd_marker = 0;
92
93 if (vol->vol_type == UBI_STATIC_VOLUME) {
94 vol->corrupted = 0;
95 vol->used_bytes = bytes;
96 vol->used_ebs = div_u64_rem(bytes, vol->usable_leb_size,
97 &vol->last_eb_bytes);
98 if (vol->last_eb_bytes)
99 vol->used_ebs += 1;
100 else
101 vol->last_eb_bytes = vol->usable_leb_size;
102 }
103
104 mutex_lock(&ubi->device_mutex);
105 err = ubi_change_vtbl_record(ubi, vol->vol_id, &vtbl_rec);
106 vol->upd_marker = 0;
107 mutex_unlock(&ubi->device_mutex);
108 return err;
109}
110
111
112
113
114
115
116
117
118
119
120
121int ubi_start_update(struct ubi_device *ubi, struct ubi_volume *vol,
122 long long bytes)
123{
124 int i, err;
125
126 dbg_gen("start update of volume %d, %llu bytes", vol->vol_id, bytes);
127 ubi_assert(!vol->updating && !vol->changing_leb);
128 vol->updating = 1;
129
130 vol->upd_buf = vmalloc(ubi->leb_size);
131 if (!vol->upd_buf)
132 return -ENOMEM;
133
134 err = set_update_marker(ubi, vol);
135 if (err)
136 return err;
137
138
139 for (i = 0; i < vol->reserved_pebs; i++) {
140 err = ubi_eba_unmap_leb(ubi, vol, i);
141 if (err)
142 return err;
143 }
144
145 if (bytes == 0) {
146 err = ubi_wl_flush(ubi, UBI_ALL, UBI_ALL);
147 if (err)
148 return err;
149
150 err = clear_update_marker(ubi, vol, 0);
151 if (err)
152 return err;
153
154 vfree(vol->upd_buf);
155 vol->updating = 0;
156 return 0;
157 }
158
159 vol->upd_ebs = div_u64(bytes + vol->usable_leb_size - 1,
160 vol->usable_leb_size);
161 vol->upd_bytes = bytes;
162 vol->upd_received = 0;
163 return 0;
164}
165
166
167
168
169
170
171
172
173
174
175int ubi_start_leb_change(struct ubi_device *ubi, struct ubi_volume *vol,
176 const struct ubi_leb_change_req *req)
177{
178 ubi_assert(!vol->updating && !vol->changing_leb);
179
180 dbg_gen("start changing LEB %d:%d, %u bytes",
181 vol->vol_id, req->lnum, req->bytes);
182 if (req->bytes == 0)
183 return ubi_eba_atomic_leb_change(ubi, vol, req->lnum, NULL, 0);
184
185 vol->upd_bytes = req->bytes;
186 vol->upd_received = 0;
187 vol->changing_leb = 1;
188 vol->ch_lnum = req->lnum;
189
190 vol->upd_buf = vmalloc(req->bytes);
191 if (!vol->upd_buf)
192 return -ENOMEM;
193
194 return 0;
195}
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226static int write_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum,
227 void *buf, int len, int used_ebs)
228{
229 int err;
230
231 if (vol->vol_type == UBI_DYNAMIC_VOLUME) {
232 int l = ALIGN(len, ubi->min_io_size);
233
234 memset(buf + len, 0xFF, l - len);
235 len = ubi_calc_data_len(ubi, buf, l);
236 if (len == 0) {
237 dbg_gen("all %d bytes contain 0xFF - skip", len);
238 return 0;
239 }
240
241 err = ubi_eba_write_leb(ubi, vol, lnum, buf, 0, len);
242 } else {
243
244
245
246
247
248
249
250
251
252 memset(buf + len, 0, vol->usable_leb_size - len);
253 err = ubi_eba_write_leb_st(ubi, vol, lnum, buf, len, used_ebs);
254 }
255
256 return err;
257}
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272int ubi_more_update_data(struct ubi_device *ubi, struct ubi_volume *vol,
273 const void __user *buf, int count)
274{
275#ifndef __UBOOT__
276 int lnum, offs, err = 0, len, to_write = count;
277#else
278 int lnum, err = 0, len, to_write = count;
279 u32 offs;
280#endif
281
282 dbg_gen("write %d of %lld bytes, %lld already passed",
283 count, vol->upd_bytes, vol->upd_received);
284
285 if (ubi->ro_mode)
286 return -EROFS;
287
288 lnum = div_u64_rem(vol->upd_received, vol->usable_leb_size, &offs);
289 if (vol->upd_received + count > vol->upd_bytes)
290 to_write = count = vol->upd_bytes - vol->upd_received;
291
292
293
294
295
296 if (offs != 0) {
297
298
299
300
301
302
303
304 len = vol->usable_leb_size - offs;
305 if (len > count)
306 len = count;
307
308 err = copy_from_user(vol->upd_buf + offs, buf, len);
309 if (err)
310 return -EFAULT;
311
312 if (offs + len == vol->usable_leb_size ||
313 vol->upd_received + len == vol->upd_bytes) {
314 int flush_len = offs + len;
315
316
317
318
319
320 ubi_assert(flush_len <= vol->usable_leb_size);
321 err = write_leb(ubi, vol, lnum, vol->upd_buf, flush_len,
322 vol->upd_ebs);
323 if (err)
324 return err;
325 }
326
327 vol->upd_received += len;
328 count -= len;
329 buf += len;
330 lnum += 1;
331 }
332
333
334
335
336
337 while (count) {
338 if (count > vol->usable_leb_size)
339 len = vol->usable_leb_size;
340 else
341 len = count;
342
343 err = copy_from_user(vol->upd_buf, buf, len);
344 if (err)
345 return -EFAULT;
346
347 if (len == vol->usable_leb_size ||
348 vol->upd_received + len == vol->upd_bytes) {
349 err = write_leb(ubi, vol, lnum, vol->upd_buf,
350 len, vol->upd_ebs);
351 if (err)
352 break;
353 }
354
355 vol->upd_received += len;
356 count -= len;
357 lnum += 1;
358 buf += len;
359 }
360
361 ubi_assert(vol->upd_received <= vol->upd_bytes);
362 if (vol->upd_received == vol->upd_bytes) {
363 err = ubi_wl_flush(ubi, UBI_ALL, UBI_ALL);
364 if (err)
365 return err;
366
367 err = clear_update_marker(ubi, vol, vol->upd_bytes);
368 if (err)
369 return err;
370 vol->updating = 0;
371 err = to_write;
372 vfree(vol->upd_buf);
373 }
374
375 return err;
376}
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392int ubi_more_leb_change_data(struct ubi_device *ubi, struct ubi_volume *vol,
393 const void __user *buf, int count)
394{
395 int err;
396
397 dbg_gen("write %d of %lld bytes, %lld already passed",
398 count, vol->upd_bytes, vol->upd_received);
399
400 if (ubi->ro_mode)
401 return -EROFS;
402
403 if (vol->upd_received + count > vol->upd_bytes)
404 count = vol->upd_bytes - vol->upd_received;
405
406 err = copy_from_user(vol->upd_buf + vol->upd_received, buf, count);
407 if (err)
408 return -EFAULT;
409
410 vol->upd_received += count;
411
412 if (vol->upd_received == vol->upd_bytes) {
413 int len = ALIGN((int)vol->upd_bytes, ubi->min_io_size);
414
415 memset(vol->upd_buf + vol->upd_bytes, 0xFF,
416 len - vol->upd_bytes);
417 len = ubi_calc_data_len(ubi, vol->upd_buf, len);
418 err = ubi_eba_atomic_leb_change(ubi, vol, vol->ch_lnum,
419 vol->upd_buf, len);
420 if (err)
421 return err;
422 }
423
424 ubi_assert(vol->upd_received <= vol->upd_bytes);
425 if (vol->upd_received == vol->upd_bytes) {
426 vol->changing_leb = 0;
427 err = count;
428 vfree(vol->upd_buf);
429 }
430
431 return err;
432}
433