blob: e0836c6c44d67e0feee99787e1df4fb8e30a3748 [file] [log] [blame]
Tanya Brokhmanea981a32015-02-12 16:32:15 +02001/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
2
3 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions are
5 * met:
6 * * Redistributions of source code must retain the above copyright
7 * notice, this list of conditions and the following disclaimer.
8 * * Redistributions in binary form must reproduce the above
9 * copyright notice, this list of conditions and the following
10 * disclaimer in the documentation and/or other materials provided
11 * with the distribution.
12 * * Neither the name of The Linux Foundation. nor the names of its
13 * contributors may be used to endorse or promote products derived
14 * from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
26 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include <stdlib.h>
30#include <string.h>
31#include <dev/flash-ubi.h>
32#include <dev/flash.h>
33#include <qpic_nand.h>
34#include <rand.h>
35
36static
37const uint32_t crc32_table[256] = {
38 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
39 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
40 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
41 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
42 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
43 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
44 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
45 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
46 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
47 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
48 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
49 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
50 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
51 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
52 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
53 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
54 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
55 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
56 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
57 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
58 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
59 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
60 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
61 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
62 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
63 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
64 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
65 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
66 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
67 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
68 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
69 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
70 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
71 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
72 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
73 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
74 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
75 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
76 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
77 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
78 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
79 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
80 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
81 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
82 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
83 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
84 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
85 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
86 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
87 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
88 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
89 0x2d02ef8dL
90};
91
92static uint32_t mtd_crc32(uint32_t crc, const void *buf, size_t size)
93{
94 const uint8_t *p = buf;
95
96 while (size--)
97 crc = crc32_table[(crc ^ *p++) & 0xff] ^ (crc >> 8);
98 return crc;
99}
100
101/**
102 * check_pattern - check if buffer contains only a certain byte pattern.
103 * @buf: buffer to check
104 * @patt: the pattern to check
105 * @size: buffer size in bytes
106 *
107 * This function returns %1 if there are only @patt bytes in @buf, and %0 if
108 * something else was also found.
109 */
110int check_pattern(const void *buf, uint8_t patt, int size)
111{
112 int i;
113
114 for (i = 0; i < size; i++)
115 if (((const uint8_t *)buf)[i] != patt)
116 return 0;
117 return 1;
118}
119
120/**
Tanya Brokhman24a088c2015-02-24 10:21:44 +0200121 * calc_data_len - calculate how much real data is stored in the buffer
122 * @page_size: min I/O of the device
123 * @buf: a buffer with the contents of the physical eraseblock
124 * @len: the buffer length
125 *
126 * This function calculates how much "real data" is stored in @buf and
127 * returns the length (in number of pages). Continuous 0xFF bytes at the end
128 * of the buffer are not considered as "real data".
129 */
130static int calc_data_len(int page_size, const void *buf, int len)
131{
132 int i;
133
134 for (i = len - 1; i >= 0; i--)
135 if (((const uint8_t *)buf)[i] != 0xFF)
136 break;
137
138 /* The resulting length must be aligned to the minimum flash I/O size */
139 len = i + 1;
140 len = (len + page_size - 1) / page_size;
141 return len;
142}
143
144/**
Tanya Brokhmanea981a32015-02-12 16:32:15 +0200145 * read_ec_hdr - read and check an erase counter header.
146 * @peb: number of the physical erase block to read the header for
147 * @ec_hdr: a &struct ubi_ec_hdr object where to store the read erase counter
148 * header
149 *
150 * This function reads erase counter header from physical eraseblock @peb and
151 * stores it in @ec_hdr. This function also checks the validity of the read
152 * header.
153 *
154 * Return codes:
155 * -1 - in case of error
156 * 0 - if PEB was found valid
157 * 1 - if PEB is empty
158 */
159static int read_ec_hdr(uint32_t peb, struct ubi_ec_hdr *ec_hdr)
160{
161 unsigned char *spare, *tmp_buf;
162 int ret = -1;
163 uint32_t crc;
164 int page_size = flash_page_size();
165 int num_pages_per_blk = flash_block_size()/page_size;
166
167 spare = (unsigned char *)malloc(flash_spare_size());
168 if (!spare)
169 {
170 dprintf(CRITICAL, "read_ec_hdr: Mem allocation failed\n");
171 return ret;
172 }
173
174 tmp_buf = (unsigned char *)malloc(page_size);
175 if (!tmp_buf)
176 {
177 dprintf(CRITICAL, "read_ec_hdr: Mem allocation failed\n");
178 goto out_tmp_buf;
179 }
180
181 if (qpic_nand_block_isbad(peb * num_pages_per_blk)) {
182 dprintf(CRITICAL, "read_ec_hdr: Bad block @ %d\n", peb);
183 goto out;
184 }
185
186 if (qpic_nand_read(peb * num_pages_per_blk, 1, tmp_buf, spare)) {
187 dprintf(CRITICAL, "read_ec_hdr: Read %d failed \n", peb);
188 goto out;
189 }
190 memcpy(ec_hdr, tmp_buf, UBI_EC_HDR_SIZE);
191
192 if (check_pattern((void *)ec_hdr, 0xFF, UBI_EC_HDR_SIZE)) {
193 ret = 1;
194 goto out;
195 }
196
197 /* Make sure we read a valid UBI EC_HEADER */
198 if (BE32(ec_hdr->magic) != (uint32_t)UBI_EC_HDR_MAGIC) {
199 dprintf(CRITICAL,
200 "read_ec_hdr: Wrong magic at peb-%d Expected: %d, received %d\n",
201 peb, UBI_EC_HDR_MAGIC, BE32(ec_hdr->magic));
202 goto out;
203 }
204
205 if (ec_hdr->version != UBI_VERSION) {
206 dprintf(CRITICAL,
207 "read_ec_hdr: Wrong version at peb-%d Expected: %d, received %d\n",
208 peb, UBI_VERSION, ec_hdr->version);
209 goto out;
210 }
211
212 if (BE64(ec_hdr->ec) > UBI_MAX_ERASECOUNTER) {
213 dprintf(CRITICAL,
214 "read_ec_hdr: Wrong ec at peb-%d: %lld \n",
215 peb, BE64(ec_hdr->ec));
216 goto out;
217 }
218
219 crc = mtd_crc32(UBI_CRC32_INIT, ec_hdr, UBI_EC_HDR_SIZE_CRC);
220 if (BE32(ec_hdr->hdr_crc) != crc) {
221 dprintf(CRITICAL,
222 "read_ec_hdr: Wrong crc at peb-%d: calculated %d, recived %d\n",
223 peb,crc, BE32(ec_hdr->hdr_crc));
224 goto out;
225 }
226
227 ret = 0;
228out:
229 free(tmp_buf);
230out_tmp_buf:
231 free(spare);
232 return ret;
233}
234
235/**
Tanya Brokhman24a088c2015-02-24 10:21:44 +0200236 * read_vid_hdr - read and check an Volume identifier header.
237 * @peb: number of the physical erase block to read the header for
238 * @vid_hdr: a &struct ubi_vid_hdr object where to store the read header
239 * @vid_hdr_offset: offset of the VID header from the beginning of the PEB
240 * (in bytes)
241 *
242 * This function reads the volume identifier header from physical
243 * eraseblock @peb and stores it in @vid_hdr. This function also checks the
244 * validity of the read header.
245 *
246 * Return codes:
247 * -1 - in case of error
248 * 0 - on success
249 * 1 - if the PEB is free (no VID hdr)
250 */
251static int read_vid_hdr(uint32_t peb, struct ubi_vid_hdr *vid_hdr,
252 int vid_hdr_offset)
253{
254 unsigned char *spare, *tmp_buf;
255 int ret = -1;
256 uint32_t crc, magic;
257 int page_size = flash_page_size();
258 int num_pages_per_blk = flash_block_size()/page_size;
259
260 spare = (unsigned char *)malloc(flash_spare_size());
261 if (!spare)
262 {
263 dprintf(CRITICAL, "read_vid_hdr: Mem allocation failed\n");
264 return ret;
265 }
266
267 tmp_buf = (unsigned char *)malloc(page_size);
268 if (!tmp_buf)
269 {
270 dprintf(CRITICAL, "read_vid_hdr: Mem allocation failed\n");
271 goto out_tmp_buf;
272 }
273
274 if (qpic_nand_block_isbad(peb * num_pages_per_blk)) {
275 dprintf(CRITICAL, "read_vid_hdr: Bad block @ %d\n", peb);
276 goto out;
277 }
278
279 if (qpic_nand_read(peb * num_pages_per_blk + vid_hdr_offset/page_size,
280 1, tmp_buf, spare)) {
281 dprintf(CRITICAL, "read_vid_hdr: Read %d failed \n", peb);
282 goto out;
283 }
284 memcpy(vid_hdr, tmp_buf, UBI_VID_HDR_SIZE);
285
286 if (check_pattern((void *)vid_hdr, 0xFF, UBI_VID_HDR_SIZE)) {
287 ret = 1;
288 goto out;
289 }
290
291 magic = BE32(vid_hdr->magic);
292 if (magic != UBI_VID_HDR_MAGIC) {
293 dprintf(CRITICAL,
294 "read_vid_hdr: Wrong magic at peb-%d Expected: %d, received %d\n",
295 peb, UBI_VID_HDR_MAGIC, BE32(vid_hdr->magic));
296 goto out;
297 }
298
299 crc = mtd_crc32(UBI_CRC32_INIT, vid_hdr, UBI_EC_HDR_SIZE_CRC);
300 if (BE32(vid_hdr->hdr_crc) != crc) {
301 dprintf(CRITICAL,
302 "read_vid_hdr: Wrong crc at peb-%d: calculated %d, received %d\n",
303 peb,crc, BE32(vid_hdr->hdr_crc));
304 goto out;
305 }
306
307 ret = 0;
308out:
309 free(tmp_buf);
310out_tmp_buf:
311 free(spare);
312 return ret;
313}
314
315/**
316 * read_leb_data - read data section of the PEB (LEB).
317 * @peb: number of the physical erase block to read the data for
318 * @leb_data: a buffer where to store the read data at
319 * @leb_size: LEB size
320 * @data_offset: offset of the data from the beginning of the PEB
321 * (in bytes)
322 *
323 * Return codes:
324 * -1 - in case of error
325 * 0 - on success
326 */
327static int read_leb_data(uint32_t peb, void *leb_data,
328 int leb_size, int data_offset)
329{
330 unsigned char *spare, *tmp_buf;
331 int ret = -1;
332 int page_size = flash_page_size();
333 int block_size = flash_block_size();
334 int num_pages_per_blk = block_size/page_size;
335
336 spare = (unsigned char *)malloc(flash_spare_size());
337 if (!spare)
338 {
339 dprintf(CRITICAL, "read_leb_data: Mem allocation failed\n");
340 return ret;
341 }
342
343 tmp_buf = (unsigned char *)malloc(leb_size);
344 if (!tmp_buf)
345 {
346 dprintf(CRITICAL, "read_leb_data: Mem allocation failed\n");
347 goto out_tmp_buf;
348 }
349
350 if (qpic_nand_block_isbad(peb * num_pages_per_blk)) {
351 dprintf(CRITICAL, "read_leb_data: Bad block @ %d\n", peb);
352 goto out;
353 }
354
355 if (qpic_nand_read(peb * num_pages_per_blk + data_offset/page_size,
356 leb_size/page_size, tmp_buf, spare)) {
357 dprintf(CRITICAL, "read_leb_data: Read %d failed \n", peb);
358 goto out;
359 }
360 memcpy(leb_data, tmp_buf, leb_size);
361
362 ret = 0;
363out:
364 free(tmp_buf);
365out_tmp_buf:
366 free(spare);
367 return ret;
368}
369
370/**
Tanya Brokhmanea981a32015-02-12 16:32:15 +0200371 * write_ec_header() - Write provided ec_header for given PEB
372 * @peb: number of the physical erase block to write the header to
373 * @new_ech: the ec_header to write
374 *
375 * Return codes:
376 * -1 - in case of error
377 * 0 - on success
378 */
379static int write_ec_header(uint32_t peb, struct ubi_ec_hdr *new_ech)
380{
381 unsigned page_size = flash_page_size();
382 int num_pages_per_blk = flash_block_size()/page_size;
383 unsigned char *buf;
384 int ret = 0;
385
386 buf = malloc(sizeof(uint8_t) * page_size);
387 if (!buf) {
388 dprintf(CRITICAL, "write_ec_header: Mem allocation failed\n");
389 return -1;
390 }
391
392 memset(buf, 0, page_size);
393 ASSERT(page_size > sizeof(*new_ech));
394 memcpy(buf, new_ech, UBI_EC_HDR_SIZE);
395 ret = qpic_nand_write(peb * num_pages_per_blk, 1, buf, 0);
396 if (ret) {
397 dprintf(CRITICAL,
398 "write_ec_header: qpic_nand_write failed with %d\n", ret);
399 ret = -1;
400 goto out;
401 }
402
403out:
404 free(buf);
405 return ret;
406}
407
408/**
Tanya Brokhman24a088c2015-02-24 10:21:44 +0200409 * write_vid_header() - Write provided vid_header for given PEB
410 * @peb: number of the physical erase block to write the header to
411 * @new_vidh: the vid_header to write
412 * @offset: vid_hdr offset in bytes from the beginning of the PEB
413 *
414 * Return codes:
415 * -1 - in case of error
416 * 0 - on success
417 */
418static int write_vid_header(uint32_t peb,
419 struct ubi_vid_hdr *new_vidh, int offset)
420{
421 unsigned page_size = flash_page_size();
422 int num_pages_per_blk = flash_block_size()/page_size;
423 unsigned char *buf;
424 int ret = 0;
425
426 buf = malloc(sizeof(uint8_t) * page_size);
427 if (!buf) {
428 dprintf(CRITICAL, "write_vid_header: Mem allocation failed\n");
429 return -1;
430 }
431
432 memset(buf, 0, page_size);
433 ASSERT(page_size > sizeof(*new_vidh));
434 memcpy(buf, new_vidh, UBI_VID_HDR_SIZE);
435 ret = qpic_nand_write(peb * num_pages_per_blk + offset/page_size,
436 1, buf, 0);
437 if (ret) {
438 dprintf(CRITICAL,
439 "write_vid_header: qpic_nand_write failed with %d\n", ret);
440 ret = -1;
441 goto out;
442 }
443
444out:
445 free(buf);
446 return ret;
447}
448
449/**
450 * write_leb_data - write data section of the PEB (LEB).
451 * @peb: number of the physical erase block to write the data for
452 * @leb_data: a data buffer to write
453 * @size: data size
454 * @data_offset: offset of the data from the beginning of the PEB
455 * (in bytes)
456 *
457 * Return codes:
458 * -1 - in case of error
459 * 0 - on success
460 */
461static int write_leb_data(uint32_t peb, void *data,
462 int size, int data_offset)
463{
464 unsigned char *tmp_buf;
465 int ret = -1;
466 int num_pages;
467 int page_size = flash_page_size();
468 int block_size = flash_block_size();
469 int num_pages_per_blk = block_size/page_size;
470
471 tmp_buf = (unsigned char *)malloc(block_size - data_offset);
472 if (!tmp_buf)
473 {
474 dprintf(CRITICAL, "write_leb_data: Mem allocation failed\n");
475 return -1;
476 }
477
478 if (size < block_size - data_offset)
479 num_pages = size / page_size;
480 else
481 num_pages = calc_data_len(page_size, data,
482 block_size - data_offset);
483 memcpy(tmp_buf, data, num_pages * page_size);
484 ret = qpic_nand_write(peb * num_pages_per_blk + data_offset/page_size,
485 num_pages, tmp_buf, 0);
486 if (ret) {
487 dprintf(CRITICAL,
488 "write_vid_header: qpic_nand_write failed with %d\n", ret);
489 ret = -1;
490 goto out;
491 }
492
493 ret = 0;
494out:
495 free(tmp_buf);
496 return ret;
497}
498
499/**
Tanya Brokhmanea981a32015-02-12 16:32:15 +0200500 * scan_partition() - Collect the ec_headers info of a given partition
501 * @ptn: partition to read the headers of
502 *
503 * Returns allocated and filled struct ubi_scan_info (si).
504 * Note: si should be released by caller.
505 */
506static struct ubi_scan_info *scan_partition(struct ptentry *ptn)
507{
508 struct ubi_scan_info *si;
509 struct ubi_ec_hdr *ec_hdr;
Tanya Brokhman24a088c2015-02-24 10:21:44 +0200510 struct ubi_vid_hdr vid_hdr;
511 unsigned i;
Tanya Brokhmanea981a32015-02-12 16:32:15 +0200512 unsigned long long sum = 0;
513 int page_size = flash_page_size();
514 int ret;
515
516 si = malloc(sizeof(*si));
517 if (!si) {
518 dprintf(CRITICAL,"scan_partition: (%s) Memory allocation failed\n",
519 ptn->name);
520 return NULL;
521 }
522
523 memset((void *)si, 0, sizeof(*si));
Tanya Brokhman24a088c2015-02-24 10:21:44 +0200524 si->pebs_data = malloc(ptn->length * sizeof(struct peb_info));
525 if (!si->pebs_data) {
Tanya Brokhmanea981a32015-02-12 16:32:15 +0200526 dprintf(CRITICAL,"scan_partition: (%s) Memory allocation failed\n",
527 ptn->name);
Tanya Brokhman24a088c2015-02-24 10:21:44 +0200528 goto out_failed_pebs;
Tanya Brokhmanea981a32015-02-12 16:32:15 +0200529 }
Tanya Brokhman24a088c2015-02-24 10:21:44 +0200530 memset((void *)si->pebs_data, 0, ptn->length * sizeof(struct peb_info));
Tanya Brokhmanea981a32015-02-12 16:32:15 +0200531
532 ec_hdr = malloc(UBI_EC_HDR_SIZE);
533 if (!ec_hdr) {
534 dprintf(CRITICAL,"scan_partition: (%s) Memory allocation failed\n",
535 ptn->name);
536 goto out_failed;
537 }
538
Tanya Brokhmanea981a32015-02-12 16:32:15 +0200539 si->vid_hdr_offs = 0;
540 si->image_seq = rand() & UBI_IMAGE_SEQ_BASE;
Tanya Brokhman24a088c2015-02-24 10:21:44 +0200541 si->vtbl_peb1 = -1;
542 si->vtbl_peb2 = -1;
543 si->fastmap_sb = -1;
Tanya Brokhmanea981a32015-02-12 16:32:15 +0200544 for (i = 0; i < ptn->length; i++){
Tanya Brokhman24a088c2015-02-24 10:21:44 +0200545 ret = read_ec_hdr(ptn->start + i, ec_hdr);
Tanya Brokhmanea981a32015-02-12 16:32:15 +0200546 switch (ret) {
547 case 1:
548 si->empty_cnt++;
Tanya Brokhman24a088c2015-02-24 10:21:44 +0200549 si->pebs_data[i].ec = UBI_MAX_ERASECOUNTER;
550 si->pebs_data[i].status = UBI_EMPTY_PEB;
Tanya Brokhmanea981a32015-02-12 16:32:15 +0200551 break;
552 case 0:
553 if (!si->vid_hdr_offs) {
554 si->vid_hdr_offs = BE32(ec_hdr->vid_hdr_offset);
555 si->data_offs = BE32(ec_hdr->data_offset);
556 if (!si->vid_hdr_offs || !si->data_offs ||
557 si->vid_hdr_offs % page_size ||
558 si->data_offs % page_size) {
559 si->bad_cnt++;
Tanya Brokhman24a088c2015-02-24 10:21:44 +0200560 si->pebs_data[i].ec = UBI_MAX_ERASECOUNTER;
Tanya Brokhmanea981a32015-02-12 16:32:15 +0200561 si->vid_hdr_offs = 0;
562 continue;
563 }
564 if (BE32(ec_hdr->vid_hdr_offset) != si->vid_hdr_offs) {
565 si->bad_cnt++;
Tanya Brokhman24a088c2015-02-24 10:21:44 +0200566 si->pebs_data[i].ec = UBI_MAX_ERASECOUNTER;
Tanya Brokhmanea981a32015-02-12 16:32:15 +0200567 continue;
568 }
569 if (BE32(ec_hdr->data_offset) != si->data_offs) {
570 si->bad_cnt++;
Tanya Brokhman24a088c2015-02-24 10:21:44 +0200571 si->pebs_data[i].ec = UBI_MAX_ERASECOUNTER;
Tanya Brokhmanea981a32015-02-12 16:32:15 +0200572 continue;
573 }
574 }
Tanya Brokhman24a088c2015-02-24 10:21:44 +0200575 si->read_image_seq = BE32(ec_hdr->image_seq);
576 si->pebs_data[i].ec = BE64(ec_hdr->ec);
577 /* Now read the VID header to find if the peb is free */
578 ret = read_vid_hdr(ptn->start + i, &vid_hdr,
579 BE32(ec_hdr->vid_hdr_offset));
580 switch (ret) {
581 case 1:
582 si->pebs_data[i].status = UBI_FREE_PEB;
583 si->free_cnt++;
584 break;
585 case 0:
586 si->pebs_data[i].status = UBI_USED_PEB;
587 si->pebs_data[i].volume = BE32(vid_hdr.vol_id);
588 if (BE32(vid_hdr.vol_id) == UBI_LAYOUT_VOLUME_ID) {
589 if (si->vtbl_peb1 == -1)
590 si->vtbl_peb1 = i;
591 else if (si->vtbl_peb2 == -1)
592 si->vtbl_peb2 = i;
593 else
594 dprintf(CRITICAL,
595 "scan_partition: Found > 2 copies of vtbl");
596 }
597 if (BE32(vid_hdr.vol_id) == UBI_FM_SB_VOLUME_ID)
598 si->fastmap_sb = i;
599 si->used_cnt++;
600 break;
601 case -1:
602 default:
603 si->bad_cnt++;
604 si->pebs_data[i].ec = UBI_MAX_ERASECOUNTER;
605 si->pebs_data[i].status = UBI_BAD_PEB;
606 break;
607 }
Tanya Brokhmanea981a32015-02-12 16:32:15 +0200608 break;
609 case -1:
610 default:
611 si->bad_cnt++;
Tanya Brokhman24a088c2015-02-24 10:21:44 +0200612 si->pebs_data[i].ec = UBI_MAX_ERASECOUNTER;
613 si->pebs_data[i].status = UBI_BAD_PEB;
Tanya Brokhmanea981a32015-02-12 16:32:15 +0200614 break;
615 }
616 }
617
Tanya Brokhman24a088c2015-02-24 10:21:44 +0200618 /* Sanity check */
619 if (si->bad_cnt + si->empty_cnt + si->free_cnt + si->used_cnt != (int)ptn->length) {
620 dprintf(CRITICAL,"scan_partition: peb count doesn't sum up \n");
621 goto out_failed;
622 }
623
Tanya Brokhmanea981a32015-02-12 16:32:15 +0200624 /*
625 * If less then 95% of the PEBs were "bad" (didn't have valid
626 * ec header), then set mean_ec = UBI_DEF_ERACE_COUNTER.
627 */
628 sum = 0;
Tanya Brokhman24a088c2015-02-24 10:21:44 +0200629 if ((si->free_cnt + si->used_cnt) &&
630 (double)((si->free_cnt + si->used_cnt) / ptn->length) * 100 > 95) {
Tanya Brokhmanea981a32015-02-12 16:32:15 +0200631 for (i = 0; i < ptn->length; i++) {
Tanya Brokhman24a088c2015-02-24 10:21:44 +0200632 if (si->pebs_data[i].ec == UBI_MAX_ERASECOUNTER)
Tanya Brokhmanea981a32015-02-12 16:32:15 +0200633 continue;
Tanya Brokhman24a088c2015-02-24 10:21:44 +0200634 sum += si->pebs_data[i].ec;
Tanya Brokhmanea981a32015-02-12 16:32:15 +0200635 }
Tanya Brokhman24a088c2015-02-24 10:21:44 +0200636 si->mean_ec = sum / (si->free_cnt + si->used_cnt);
Tanya Brokhmanea981a32015-02-12 16:32:15 +0200637 } else {
638 si->mean_ec = UBI_DEF_ERACE_COUNTER;
639 }
640 free(ec_hdr);
641 return si;
642
643out_failed:
Tanya Brokhman24a088c2015-02-24 10:21:44 +0200644 free(si->pebs_data);
645out_failed_pebs:
Tanya Brokhmanea981a32015-02-12 16:32:15 +0200646 free(si);
647 return NULL;
648}
649
650/**
651 * update_ec_header() - Update provided ec_header
652 * @si: pointer to struct ubi_scan_info, holding the collected
653 * ec_headers information of the partition
654 * @index: index in si->ec[] of this peb. Relative to ptn->start
655 * @new_header: False if this is an update of an existing header.
656 * True if new header needs to be filled in
657 */
658static void update_ec_header(struct ubi_ec_hdr *old_ech,
659 const struct ubi_scan_info *si,
660 int index, bool new_header)
661{
662 uint32_t crc;
663
Tanya Brokhman24a088c2015-02-24 10:21:44 +0200664 if (si->pebs_data[index].ec < UBI_MAX_ERASECOUNTER)
665 old_ech->ec = BE64(si->pebs_data[index].ec + 1);
Tanya Brokhmanea981a32015-02-12 16:32:15 +0200666 else
667 old_ech->ec = BE64(si->mean_ec);
668
669 if (new_header) {
670 old_ech->vid_hdr_offset = BE32(si->vid_hdr_offs);
671 old_ech->data_offset = BE32(si->data_offs);
672 old_ech->magic = BE32(UBI_EC_HDR_MAGIC);
673 old_ech->version = UBI_VERSION;
674 }
675 old_ech->image_seq = BE32(si->image_seq);
676 crc = mtd_crc32(UBI_CRC32_INIT,
677 (const void *)old_ech, UBI_EC_HDR_SIZE_CRC);
678 old_ech->hdr_crc = BE32(crc);
679}
680
Tanya Brokhman24a088c2015-02-24 10:21:44 +0200681
682static void update_vid_header(struct ubi_vid_hdr *vid_hdr,
683 const struct ubi_scan_info *si, uint32_t vol_id,
684 uint32_t lnum, uint32_t data_pad)
Tanya Brokhmanea981a32015-02-12 16:32:15 +0200685{
Tanya Brokhman24a088c2015-02-24 10:21:44 +0200686 uint32_t crc;
Tanya Brokhmanea981a32015-02-12 16:32:15 +0200687
Tanya Brokhman24a088c2015-02-24 10:21:44 +0200688 vid_hdr->vol_type = UBI_VID_DYNAMIC;
689 vid_hdr->sqnum = BE64(si->image_seq);
690 vid_hdr->vol_id = BE32(vol_id);
691 vid_hdr->lnum = BE32(lnum);
692 vid_hdr->compat = 0;
693 vid_hdr->data_pad = BE32(data_pad);
Tanya Brokhmanea981a32015-02-12 16:32:15 +0200694
Tanya Brokhman24a088c2015-02-24 10:21:44 +0200695 vid_hdr->magic = BE32(UBI_VID_HDR_MAGIC);
696 vid_hdr->version = UBI_VERSION;
697 crc = mtd_crc32(UBI_CRC32_INIT,
698 (const void *)vid_hdr, UBI_VID_HDR_SIZE_CRC);
699 vid_hdr->hdr_crc = BE32(crc);
Tanya Brokhmanea981a32015-02-12 16:32:15 +0200700}
701
702/**
Tanya Brokhmanc52aeb82015-01-27 11:08:50 +0200703 * fastmap_present - returns true if Fastmap superblock is found
704 * @data: raw data to test
705 *
706 * This function returns 1 if the provided PEB data contains
707 * Fastmap superblock, 0 otherwise
708 */
709static int fastmap_present(const void *data){
710 struct ubi_ec_hdr *ec_hdr = (struct ubi_ec_hdr *)(data);
711 struct ubi_vid_hdr *vid_hdr;
712
713 vid_hdr = (struct ubi_vid_hdr *)(data + BE32(ec_hdr->vid_hdr_offset));
714 if (BE32(vid_hdr->vol_id) == UBI_FM_SB_VOLUME_ID)
715 return 1;
716 else
717 return 0;
718}
719
720/**
721 * ubi_erase_peb - Erase PEB and update EC header
722 * @peb_num: number of the PEB to erase
Tanya Brokhmanc52aeb82015-01-27 11:08:50 +0200723 * @si: UBI scan information
724 * @ptn_start: first PEB of the flashed partition
725 *
726 * This function erases the given PEB (if required) and writes a new EC
727 * header for it.
728 *
729 * Returns: -1 on error
730 * 0 on success
731 */
Tanya Brokhman72925d42015-06-07 15:52:15 +0300732static int ubi_erase_peb(int peb_num, struct ubi_scan_info *si,
733 int ptn_start)
Tanya Brokhmanc52aeb82015-01-27 11:08:50 +0200734{
735 struct ubi_ec_hdr new_ech;
736 int page_size = flash_page_size();
737 int num_pages_per_blk = flash_block_size() / page_size;
738 int ret;
739
Tanya Brokhman72925d42015-06-07 15:52:15 +0300740 if (qpic_nand_blk_erase(peb_num * num_pages_per_blk)) {
Tanya Brokhman24a088c2015-02-24 10:21:44 +0200741 dprintf(INFO, "ubi_erase_peb: erase of %d failed\n", peb_num);
Tanya Brokhmanc52aeb82015-01-27 11:08:50 +0200742 return -1;
743 }
744 memset(&new_ech, 0xff, sizeof(new_ech));
745 update_ec_header(&new_ech, si, peb_num - ptn_start, true);
746
747 /* Write new ec_header */
748 ret = write_ec_header(peb_num, &new_ech);
749 if (ret) {
Tanya Brokhman24a088c2015-02-24 10:21:44 +0200750 dprintf(CRITICAL, "ubi_erase_peb: write ec_header to %d failed\n",
Tanya Brokhmanc52aeb82015-01-27 11:08:50 +0200751 peb_num);
752 return -1;
753 }
Tanya Brokhman24a088c2015-02-24 10:21:44 +0200754 si->pebs_data[peb_num - ptn_start].status = UBI_FREE_PEB;
Tanya Brokhmanc52aeb82015-01-27 11:08:50 +0200755 return 0;
756}
Tanya Brokhmanf9343162015-01-27 13:37:41 +0200757
758/**
759 * remove_F_flag() - Turn off space-fixup flag in the ubifs superblock
760 * @data: pointer to the peb to check in the flashed image
761 *
762 * The UBIFS Superblock will be located at LEB 0 of the image. LEB 0 will be
763 * mapped as follows:
764 * If the image contains Fastmap superblock:
765 * - LEB 0 will be at PEB3
766 * else:
767 * - LEB 0 will be at PEB2
768 */
769static void remove_F_flag(const void *leb_data)
770{
771 struct ubifs_ch *ch;
772 struct ubifs_sb_node *ubifs_sb;
773 struct ubi_ec_hdr *ech;
774 struct ubi_vid_hdr *vidh;
775 int vol_id;
776
777 ech = (struct ubi_ec_hdr *)leb_data;
778 vidh = (struct ubi_vid_hdr *)(leb_data + BE32(ech->vid_hdr_offset));
779 vol_id = BE32(vidh->vol_id);
780
781 if (vol_id > UBI_MAX_VOLUMES &&
782 vol_id != UBI_LAYOUT_VOLUME_ID &&
783 vol_id != UBI_FM_SB_VOLUME_ID)
784 return;
785
786 ubifs_sb = (struct ubifs_sb_node *)(leb_data + BE32(ech->data_offset));
787 ch = (struct ubifs_ch *)ubifs_sb;
788 if (ch->node_type != UBIFS_SB_NODE)
789 return;
790 if (ubifs_sb->flags & UBIFS_FLG_SPACE_FIXUP) {
791 ubifs_sb->flags &= (~UBIFS_FLG_SPACE_FIXUP);
792 ch->crc = mtd_crc32(UBIFS_CRC32_INIT, (void *)ubifs_sb + 8,
793 sizeof(struct ubifs_sb_node) - 8);
794 }
795}
796
Tanya Brokhmanc52aeb82015-01-27 11:08:50 +0200797/**
Tanya Brokhmanea981a32015-02-12 16:32:15 +0200798 * flash_ubi_img() - Write the provided (UBI) image to given partition
799 * @ptn: partition to write the image to
800 * @data: the image to write
801 * @size: size of the image to write
802 *
803 * Return codes:
804 * -1 - in case of error
805 * 0 - on success
806 */
807int flash_ubi_img(struct ptentry *ptn, void *data, unsigned size)
808{
809 struct ubi_scan_info *si;
810 struct ubi_ec_hdr *old_ech;
Tanya Brokhmanea981a32015-02-12 16:32:15 +0200811 uint32_t curr_peb = ptn->start;
812 void *img_peb;
813 unsigned page_size = flash_page_size();
814 unsigned block_size = flash_block_size();
815 int num_pages_per_blk = block_size / page_size;
816 int num_pages;
Tanya Brokhman72925d42015-06-07 15:52:15 +0300817 int ret;
Tanya Brokhmanc52aeb82015-01-27 11:08:50 +0200818 int bad_blocks_cnt = 0;
Nikhilesh Reddy66c00b02015-12-07 13:32:14 -0800819 uint32_t fmsb_peb = UINT_MAX;
820 int is_fmsb_peb_valid = 0;
Mayank Groverf2f354a2017-06-06 18:42:11 +0530821 unsigned peb_valid_sz= 0;
Tanya Brokhmanea981a32015-02-12 16:32:15 +0200822
823 si = scan_partition(ptn);
824 if (!si) {
825 dprintf(CRITICAL, "flash_ubi_img: scan_partition failed\n");
826 return -1;
827 }
828
829 /*
830 * In case si->vid_hdr_offs is still -1 (non UBI image was
831 * flashed on device, get the value from the image to flush
832 */
833 if (!si->vid_hdr_offs){
834 struct ubi_ec_hdr *echd = (struct ubi_ec_hdr *)data;
835 si->vid_hdr_offs = BE32(echd->vid_hdr_offset);
836 si->data_offs = BE32(echd->data_offset);
837 }
838
Tanya Brokhmanea981a32015-02-12 16:32:15 +0200839 /* Update the "to be" flashed image and flash it */
840 img_peb = data;
841 while (size && curr_peb < ptn->start + ptn->length) {
Tanya Brokhman72925d42015-06-07 15:52:15 +0300842 if (qpic_nand_blk_erase(curr_peb * num_pages_per_blk)) {
Tanya Brokhmanea981a32015-02-12 16:32:15 +0200843 dprintf(CRITICAL, "flash_ubi_img: erase of %d failed\n",
844 curr_peb);
Tanya Brokhmanc52aeb82015-01-27 11:08:50 +0200845 bad_blocks_cnt++;
Tanya Brokhmanea981a32015-02-12 16:32:15 +0200846 curr_peb++;
847 continue;
848 }
Mayank Groverf2f354a2017-06-06 18:42:11 +0530849
Tanya Brokhmanea981a32015-02-12 16:32:15 +0200850 if (size < block_size)
851 num_pages = size / page_size;
852 else
853 num_pages = calc_data_len(page_size, img_peb, block_size);
Mayank Groverf2f354a2017-06-06 18:42:11 +0530854
855 /* Total size of valid data in peb */
856 peb_valid_sz = num_pages * page_size;
857
Mayank Grover07390622017-07-07 17:58:54 +0530858 if (size < UBI_MAGIC_SIZE)
859 {
860 dprintf(CRITICAL, "flash_ubi_img: invalid size provided.\n");
861 return -1;
862 }
863
Mayank Groverf2f354a2017-06-06 18:42:11 +0530864 /*
865 * Check for oob access if any in img_peb.
866 */
867 if (memcmp(img_peb, UBI_MAGIC, UBI_MAGIC_SIZE) ||
868 BE32(((struct ubi_ec_hdr *)img_peb)->vid_hdr_offset) > peb_valid_sz ||
869 BE32(((struct ubi_ec_hdr *)img_peb)->data_offset) > peb_valid_sz)
870 {
871 dprintf(CRITICAL, "flash_ubi_img: invalid image peb found\n");
872 return -1;
873 }
874
875 remove_F_flag(img_peb);
876 /* Update the ec_header in the image */
877 old_ech = (struct ubi_ec_hdr *)img_peb;
878 update_ec_header(old_ech, si, curr_peb - ptn->start, false);
Tanya Brokhmanea981a32015-02-12 16:32:15 +0200879 /* Write one block from image */
880 ret = qpic_nand_write(curr_peb * num_pages_per_blk,
881 num_pages, img_peb, 0);
882 if (ret) {
883 dprintf(CRITICAL, "flash_ubi_img: writing to peb-%d failed\n",
884 curr_peb);
Tanya Brokhmanc52aeb82015-01-27 11:08:50 +0200885 bad_blocks_cnt++;
Tanya Brokhmanea981a32015-02-12 16:32:15 +0200886 curr_peb++;
887 continue;
888 }
889 if (size < block_size)
890 size = 0;
891 else
892 size -= block_size;
Tanya Brokhmanc52aeb82015-01-27 11:08:50 +0200893
Nikhilesh Reddy66c00b02015-12-07 13:32:14 -0800894 if (fastmap_present(img_peb)) {
Tanya Brokhmanc52aeb82015-01-27 11:08:50 +0200895 fmsb_peb = curr_peb;
Nikhilesh Reddy66c00b02015-12-07 13:32:14 -0800896 is_fmsb_peb_valid = 1;
897 }
Tanya Brokhmanea981a32015-02-12 16:32:15 +0200898 img_peb += flash_block_size();
899 curr_peb++;
900 }
901
902 if (size) {
903 dprintf(CRITICAL,
904 "flash_ubi_img: Not enough good blocks to flash image!");
905 ret = -1;
906 goto out;
907 }
908
909 /* Erase and write ec_header for the rest of the blocks */
Tanya Brokhmanc52aeb82015-01-27 11:08:50 +0200910 for (; curr_peb < ptn->start + ptn->length; curr_peb++)
Tanya Brokhman72925d42015-06-07 15:52:15 +0300911 if (ubi_erase_peb(curr_peb, si, ptn->start))
Tanya Brokhmanc52aeb82015-01-27 11:08:50 +0200912 bad_blocks_cnt++;
Tanya Brokhmanea981a32015-02-12 16:32:15 +0200913
Tanya Brokhmanea981a32015-02-12 16:32:15 +0200914 ret = 0;
Tanya Brokhmanc52aeb82015-01-27 11:08:50 +0200915 /*
916 * If flashed image contains fastmap data and bad blocks were found
917 * we need to invalidate the flashed fastmap since it isn't accurate
918 * anymore.
919 */
Nikhilesh Reddy66c00b02015-12-07 13:32:14 -0800920 if (bad_blocks_cnt && (is_fmsb_peb_valid == 1)) {
921 dprintf(CRITICAL, "flash_ubi_img: invalidate fmsb (fmsb_peb = %u)\n",
922 fmsb_peb);
923 ret = ubi_erase_peb(fmsb_peb, si, ptn->start);
Tanya Brokhmanc52aeb82015-01-27 11:08:50 +0200924 }
925
Tanya Brokhmanea981a32015-02-12 16:32:15 +0200926out:
Tanya Brokhman24a088c2015-02-24 10:21:44 +0200927 free(si->pebs_data);
Tanya Brokhmanea981a32015-02-12 16:32:15 +0200928 free(si);
929 return ret;
930}
Tanya Brokhman24a088c2015-02-24 10:21:44 +0200931
932/**
933 * find_volume() - Find given volume in a partition by it's name
934 * @si: pointer to struct ubi_scan_info
935 * @ptn_start: PEB number the partition begins at
936 * @vol_name: name of the volume to search for
937 * @vol_info: info obout the found volume
938 *
939 * This functions reads the volume table, then iterates over all its records
940 * and searches for a volume with a given name. If found, the volume table
941 * record describing this volume is returned at @vol_info. The volume
942 * id returned as a return code of the function.
943 *
944 * Returns:
945 * -1 - if the volume was not found
946 * volume in dex when found
947 */
948static int find_volume(struct ubi_scan_info *si, int ptn_start,
949 const char *vol_name, struct ubi_vtbl_record *vol_info)
950{
951 int i, vtbl_records, vtbl_peb, ret = -1;
952 int block_size = flash_block_size();
953 void *leb_data;
954 struct ubi_vtbl_record *curr_vol;
955
956 if (si->vtbl_peb1 < 0) {
957 dprintf(CRITICAL,"find_volume: vtbl not found \n");
958 return -1;
959 }
960 vtbl_peb = si->vtbl_peb1;
961
962 vtbl_records = (block_size - si->data_offs) / UBI_VTBL_RECORD_SIZE;
963 if (vtbl_records > UBI_MAX_VOLUMES)
964 vtbl_records = UBI_MAX_VOLUMES;
965
966 leb_data = malloc(block_size - si->data_offs);
967 if (!leb_data) {
968 dprintf(CRITICAL,"find_volume: Memory allocation failed\n");
969 goto out_free_leb;
970 }
971retry:
972 /* First read the volume table */
973 if (read_leb_data(vtbl_peb + ptn_start, leb_data,
974 block_size - si->data_offs, si->data_offs)) {
975 dprintf(CRITICAL,"find_volume: read_leb_data failed\n");
976 if (vtbl_peb == si->vtbl_peb1 && si->vtbl_peb2 != -1) {
977 vtbl_peb = si->vtbl_peb2;
978 goto retry;
979 }
980 goto out_free_leb;
981 }
982
983 /* Now search for the required volume ID */
984 for (i = 0; i < vtbl_records; i++) {
985 curr_vol = (struct ubi_vtbl_record *)
986 (leb_data + UBI_VTBL_RECORD_SIZE*i);
987 if (!curr_vol->vol_type)
988 break;
989 if (!strcmp((char *)curr_vol->name, vol_name)) {
990 ret = i;
991 memcpy((void*)vol_info, curr_vol, sizeof(struct ubi_vtbl_record));
992 break;
993 }
994 }
995
996out_free_leb:
997 free(leb_data);
998 return ret;
999}
1000
1001/**
1002 * write_one_peb() - writes data to a PEB, including VID header
1003 * @curr_peb - PEB to write to
1004 * @ptn_start: number of first PEB of the partition
1005 * @si: pointer to struct ubi_scan_info
1006 * @idx: index of required PEB in si->pebs_data array
1007 * @lnum: lun number this LEB belongs to
1008 * @vol_id: volume ID this PEB belongs to
1009 * @data: data to write
1010 * @size: size of the data
1011 *
1012 * Assumption: EC header correctly written and PEB erased
1013 *
1014 * Return codes:
1015 * -1 - in case of error
1016 * 0 - on success
1017 */
1018static int write_one_peb(int curr_peb, int ptn_start,
1019 struct ubi_scan_info *si,
1020 int lnum, int vol_id, void* data, int size)
1021{
1022 int ret;
1023 struct ubi_vid_hdr vidh;
1024
1025 memset((void *)&vidh, 0, UBI_VID_HDR_SIZE);
1026 update_vid_header(&vidh, si, vol_id, lnum, 0);
1027 if (write_vid_header(curr_peb + ptn_start, &vidh, si->vid_hdr_offs)) {
1028 dprintf(CRITICAL,
1029 "update_ubi_vol: write_vid_header for peb %d failed \n",
1030 curr_peb);
1031 ret = -1;
1032 goto out;
1033 }
1034
1035 /* now write the data */
1036 ret = write_leb_data(curr_peb + ptn_start, data, size, si->data_offs);
1037 if (ret)
1038 dprintf(CRITICAL, "update_ubi_vol: writing data to peb-%d failed\n",
1039 curr_peb);
1040 else
1041 si->pebs_data[curr_peb].status = UBI_USED_PEB;
1042out:
1043 return ret;
1044}
1045
1046/**
1047 * update_ubi_vol() - Write the provided (UBI) image to given volume
1048 * @ptn: partition holding the required volume
1049 * @data: the image to write
1050 * @size: size of the image to write
1051 *
1052 * Return codes:
1053 * -1 - in case of error
1054 * 0 - on success
1055 */
1056int update_ubi_vol(struct ptentry *ptn, const char* vol_name,
1057 void *data, unsigned size)
1058{
1059 struct ubi_scan_info *si;
1060 int vol_id, vol_pebs, curr_peb = 0, ret = -1;
1061 unsigned block_size = flash_block_size();
1062 void *img_peb;
1063 struct ubi_vtbl_record curr_vol;
1064 int img_pebs, lnum = 0;
1065
1066 si = scan_partition(ptn);
1067 if (!si) {
1068 dprintf(CRITICAL, "update_ubi_vol: scan_partition failed\n");
1069 return -1;
1070 }
1071 if (si->read_image_seq)
1072 si->image_seq = si->read_image_seq;
1073
1074 vol_id = find_volume(si, ptn->start, vol_name, &curr_vol);
1075 if (vol_id == -1) {
1076 dprintf(CRITICAL, "update_ubi_vol: dint find volume\n");
1077 goto out;
1078 }
1079 if (si->fastmap_sb > -1 &&
Tanya Brokhman72925d42015-06-07 15:52:15 +03001080 ubi_erase_peb(ptn->start + si->fastmap_sb, si, ptn->start)) {
Tanya Brokhman24a088c2015-02-24 10:21:44 +02001081 dprintf(CRITICAL, "update_ubi_vol: fastmap invalidation failed\n");
1082 goto out;
1083 }
1084
1085 img_pebs = size / (block_size - si->data_offs);
1086 if (size % (block_size - si->data_offs))
1087 img_pebs++;
1088
1089 vol_pebs = BE32(curr_vol.reserved_pebs);
1090 if (img_pebs > vol_pebs) {
1091 dprintf(CRITICAL,
1092 "update_ubi_vol: Provided image is too big. Requires %d PEBs, avail. only %d\n",
1093 img_pebs, vol_pebs);
1094 goto out;
1095 }
1096
1097 /* First erase all volume used PEBs */
1098 curr_peb = 0;
1099 while (curr_peb < (int)ptn->length) {
1100 if (si->pebs_data[curr_peb].status != UBI_USED_PEB ||
1101 si->pebs_data[curr_peb].volume != vol_id) {
1102 curr_peb++;
1103 continue;
1104 }
Tanya Brokhman72925d42015-06-07 15:52:15 +03001105 if (ubi_erase_peb(ptn->start + curr_peb, si, ptn->start))
Tanya Brokhman24a088c2015-02-24 10:21:44 +02001106 goto out;
1107 curr_peb++;
1108 }
1109
1110 /* Flash the image */
1111 img_peb = data;
1112 lnum = 0;
1113 for (curr_peb = 0;
1114 curr_peb < (int)ptn->length && size && vol_pebs;
1115 curr_peb++) {
1116 if (si->pebs_data[curr_peb].status != UBI_FREE_PEB &&
1117 si->pebs_data[curr_peb].status != UBI_EMPTY_PEB)
1118 continue;
1119
1120 if (write_one_peb(curr_peb, ptn->start, si,
1121 lnum++, vol_id, img_peb,
1122 (size < block_size - si->data_offs ? size :
1123 block_size - si->data_offs))) {
1124 dprintf(CRITICAL, "update_ubi_vol: write_one_peb failed\n");
1125 goto out;
1126 }
1127 if (size < block_size - si->data_offs)
1128 size = 0;
1129 else
1130 size -= (block_size - si->data_offs);
1131 vol_pebs--;
1132 img_peb += block_size - si->data_offs;
1133 }
1134
1135 if (size) {
1136 dprintf(CRITICAL,
1137 "update_ubi_vol: Not enough available PEBs for writing the volume\n");
1138 goto out;
1139 }
1140 ret = 0;
1141out:
1142 free(si->pebs_data);
1143 free(si);
1144 return ret;
1145}
1146
1147