Commit cc0f08cd347ea9741375a70c490c6bee684f7bac

Authored by Steve Rae
Committed by Tom Rini
1 parent 64ece84854

fastboot: sparse: resync common/image-sparse.c (part 1)

This file originally came from upstream code.

While retaining the storage abstraction feature, this is the first
set of the changes required to resync with the
  cmd_flash_mmc_sparse_img()
in the file
  aboot.c
from
  https://us.codeaurora.org/cgit/quic/la/kernel/lk/plain/app/aboot/aboot.c?h=LE.BR.1.2.1

Signed-off-by: Steve Rae <srae@broadcom.com>

Showing 4 changed files with 210 additions and 352 deletions Side-by-side Diff

... ... @@ -7,12 +7,10 @@
7 7 #include <config.h>
8 8 #include <common.h>
9 9 #include <blk.h>
10   -#include <errno.h>
11 10 #include <fastboot.h>
12 11 #include <fb_mmc.h>
13 12 #include <image-sparse.h>
14 13 #include <part.h>
15   -#include <sparse_format.h>
16 14 #include <mmc.h>
17 15 #include <div64.h>
18 16  
19 17  
20 18  
21 19  
... ... @@ -48,22 +46,13 @@
48 46 return ret;
49 47 }
50 48  
51   -
52   -static int fb_mmc_sparse_write(struct sparse_storage *storage,
53   - void *priv,
54   - unsigned int offset,
55   - unsigned int size,
56   - char *data)
  49 +static lbaint_t fb_mmc_sparse_write(struct sparse_storage *info,
  50 + lbaint_t blk, lbaint_t blkcnt, const void *buffer)
57 51 {
58   - struct fb_mmc_sparse *sparse = priv;
  52 + struct fb_mmc_sparse *sparse = info->priv;
59 53 struct blk_desc *dev_desc = sparse->dev_desc;
60   - int ret;
61 54  
62   - ret = blk_dwrite(dev_desc, offset, size, data);
63   - if (!ret)
64   - return -EIO;
65   -
66   - return ret;
  55 + return blk_dwrite(dev_desc, blk, blkcnt, buffer);
67 56 }
68 57  
69 58 static void write_raw_image(struct blk_desc *dev_desc, disk_partition_t *info,
70 59  
71 60  
72 61  
73 62  
74 63  
... ... @@ -139,26 +128,25 @@
139 128  
140 129 if (is_sparse_image(download_buffer)) {
141 130 struct fb_mmc_sparse sparse_priv;
142   - sparse_storage_t sparse;
  131 + struct sparse_storage sparse;
143 132  
144 133 sparse_priv.dev_desc = dev_desc;
145 134  
146   - sparse.block_sz = info.blksz;
  135 + sparse.blksz = info.blksz;
147 136 sparse.start = info.start;
148 137 sparse.size = info.size;
149   - sparse.name = cmd;
150 138 sparse.write = fb_mmc_sparse_write;
151 139  
152 140 printf("Flashing sparse image at offset " LBAFU "\n",
153   - info.start);
  141 + sparse.start);
154 142  
155   - store_sparse_image(&sparse, &sparse_priv, download_buffer);
  143 + sparse.priv = &sparse_priv;
  144 + write_sparse_image(&sparse, cmd, download_buffer,
  145 + download_bytes, response_str);
156 146 } else {
157 147 write_raw_image(dev_desc, &info, cmd, download_buffer,
158 148 download_bytes);
159 149 }
160   -
161   - fastboot_okay(response_str, "");
162 150 }
163 151  
164 152 void fb_mmc_erase(const char *cmd, char *response)
... ... @@ -10,7 +10,6 @@
10 10  
11 11 #include <fastboot.h>
12 12 #include <image-sparse.h>
13   -#include <sparse_format.h>
14 13  
15 14 #include <linux/mtd/mtd.h>
16 15 #include <jffs2/jffs2.h>
... ... @@ -19,7 +18,7 @@
19 18 static char *response_str;
20 19  
21 20 struct fb_nand_sparse {
22   - struct mtd_info *nand;
  21 + struct mtd_info *mtd;
23 22 struct part_info *part;
24 23 };
25 24  
26 25  
27 26  
28 27  
29 28  
... ... @@ -105,30 +104,32 @@
105 104 buffer, flags);
106 105 }
107 106  
108   -static int fb_nand_sparse_write(struct sparse_storage *storage,
109   - void *priv,
110   - unsigned int offset,
111   - unsigned int size,
112   - char *data)
  107 +static lbaint_t fb_nand_sparse_write(struct sparse_storage *info,
  108 + lbaint_t blk, lbaint_t blkcnt, const void *buffer)
113 109 {
114   - struct fb_nand_sparse *sparse = priv;
  110 + struct fb_nand_sparse *sparse = info->priv;
115 111 size_t written;
116 112 int ret;
117 113  
118   - ret = _fb_nand_write(sparse->nand, sparse->part, data,
119   - offset * storage->block_sz,
120   - size * storage->block_sz, &written);
  114 + ret = _fb_nand_write(sparse->mtd, sparse->part, (void *)buffer,
  115 + blk * info->blksz,
  116 + blkcnt * info->blksz, &written);
121 117 if (ret < 0) {
122 118 printf("Failed to write sparse chunk\n");
123 119 return ret;
124 120 }
125 121  
126   - return written / storage->block_sz;
  122 +/* TODO - verify that the value "written" includes the "bad-blocks" ... */
  123 +
  124 + /*
  125 + * the return value must be 'blkcnt' ("good-blocks") plus the
  126 + * number of "bad-blocks" encountered within this space...
  127 + */
  128 + return written / info->blksz;
127 129 }
128 130  
129   -void fb_nand_flash_write(const char *partname,
130   - void *download_buffer, unsigned int download_bytes,
131   - char *response)
  131 +void fb_nand_flash_write(const char *cmd, void *download_buffer,
  132 + unsigned int download_bytes, char *response)
132 133 {
133 134 struct part_info *part;
134 135 struct mtd_info *mtd = NULL;
... ... @@ -137,7 +138,7 @@
137 138 /* initialize the response buffer */
138 139 response_str = response;
139 140  
140   - ret = fb_nand_lookup(partname, response, &mtd, &part);
  141 + ret = fb_nand_lookup(cmd, response, &mtd, &part);
141 142 if (ret) {
142 143 error("invalid NAND device");
143 144 fastboot_fail(response_str, "invalid NAND device");
144 145  
145 146  
146 147  
... ... @@ -150,19 +151,22 @@
150 151  
151 152 if (is_sparse_image(download_buffer)) {
152 153 struct fb_nand_sparse sparse_priv;
153   - sparse_storage_t sparse;
  154 + struct sparse_storage sparse;
154 155  
155   - sparse_priv.nand = mtd;
  156 + sparse_priv.mtd = mtd;
156 157 sparse_priv.part = part;
157 158  
158   - sparse.block_sz = mtd->writesize;
159   - sparse.start = part->offset / sparse.block_sz;
160   - sparse.size = part->size / sparse.block_sz;
161   - sparse.name = part->name;
  159 + sparse.blksz = mtd->writesize;
  160 + sparse.start = part->offset / sparse.blksz;
  161 + sparse.size = part->size / sparse.blksz;
162 162 sparse.write = fb_nand_sparse_write;
163 163  
164   - ret = store_sparse_image(&sparse, &sparse_priv,
165   - download_buffer);
  164 + printf("Flashing sparse image at offset " LBAFU "\n",
  165 + sparse.start);
  166 +
  167 + sparse.priv = &sparse_priv;
  168 + write_sparse_image(&sparse, cmd, download_buffer,
  169 + download_bytes, response_str);
166 170 } else {
167 171 printf("Flashing raw image at offset 0x%llx\n",
168 172 part->offset);
... ... @@ -182,7 +186,7 @@
182 186 fastboot_okay(response_str, "");
183 187 }
184 188  
185   -void fb_nand_erase(const char *partname, char *response)
  189 +void fb_nand_erase(const char *cmd, char *response)
186 190 {
187 191 struct part_info *part;
188 192 struct mtd_info *mtd = NULL;
... ... @@ -191,7 +195,7 @@
191 195 /* initialize the response buffer */
192 196 response_str = response;
193 197  
194   - ret = fb_nand_lookup(partname, response, &mtd, &part);
  198 + ret = fb_nand_lookup(cmd, response, &mtd, &part);
195 199 if (ret) {
196 200 error("invalid NAND device");
197 201 fastboot_fail(response_str, "invalid NAND device");
common/image-sparse.c
... ... @@ -36,55 +36,45 @@
36 36  
37 37 #include <config.h>
38 38 #include <common.h>
39   -#include <div64.h>
40   -#include <errno.h>
41 39 #include <image-sparse.h>
  40 +#include <div64.h>
42 41 #include <malloc.h>
43 42 #include <part.h>
44 43 #include <sparse_format.h>
  44 +#include <fastboot.h>
45 45  
46 46 #include <linux/math64.h>
47 47  
48   -typedef struct sparse_buffer {
49   - void *data;
50   - u32 length;
51   - u32 repeat;
52   - u16 type;
53   -} sparse_buffer_t;
54   -
55   -static unsigned int sparse_get_chunk_data_size(sparse_header_t *sparse,
56   - chunk_header_t *chunk)
  48 +void write_sparse_image(
  49 + struct sparse_storage *info, const char *part_name,
  50 + void *data, unsigned sz, char *response_str)
57 51 {
58   - return chunk->total_sz - sparse->chunk_hdr_sz;
59   -}
  52 + lbaint_t blk;
  53 + lbaint_t blkcnt;
  54 + lbaint_t blks;
  55 + uint32_t bytes_written = 0;
  56 + unsigned int chunk;
  57 + unsigned int offset;
  58 + unsigned int chunk_data_sz;
  59 + uint32_t *fill_buf = NULL;
  60 + uint32_t fill_val;
  61 + sparse_header_t *sparse_header;
  62 + chunk_header_t *chunk_header;
  63 + uint32_t total_blocks = 0;
  64 + int i;
60 65  
61   -static unsigned int sparse_block_size_to_storage(unsigned int size,
62   - sparse_storage_t *storage,
63   - sparse_header_t *sparse)
64   -{
65   - return (unsigned int)lldiv((uint64_t)size * sparse->blk_sz,
66   - storage->block_sz);
67   -}
  66 + /* Read and skip over sparse image header */
  67 + sparse_header = (sparse_header_t *)data;
68 68  
69   -static bool sparse_chunk_has_buffer(chunk_header_t *chunk)
70   -{
71   - switch (chunk->chunk_type) {
72   - case CHUNK_TYPE_RAW:
73   - case CHUNK_TYPE_FILL:
74   - return true;
75   -
76   - default:
77   - return false;
  69 + data += sparse_header->file_hdr_sz;
  70 + if (sparse_header->file_hdr_sz > sizeof(sparse_header_t)) {
  71 + /*
  72 + * Skip the remaining bytes in a header that is longer than
  73 + * we expected.
  74 + */
  75 + data += (sparse_header->file_hdr_sz - sizeof(sparse_header_t));
78 76 }
79   -}
80 77  
81   -static sparse_header_t *sparse_parse_header(void **data)
82   -{
83   - /* Read and skip over sparse image header */
84   - sparse_header_t *sparse_header = (sparse_header_t *) *data;
85   -
86   - *data += sparse_header->file_hdr_sz;
87   -
88 78 debug("=== Sparse Image Header ===\n");
89 79 debug("magic: 0x%x\n", sparse_header->magic);
90 80 debug("major_version: 0x%x\n", sparse_header->major_version);
91 81  
92 82  
93 83  
94 84  
95 85  
96 86  
97 87  
98 88  
99 89  
100 90  
101 91  
102 92  
103 93  
104 94  
105 95  
106 96  
107 97  
108 98  
... ... @@ -95,290 +85,165 @@
95 85 debug("total_blks: %d\n", sparse_header->total_blks);
96 86 debug("total_chunks: %d\n", sparse_header->total_chunks);
97 87  
98   - return sparse_header;
99   -}
100   -
101   -static int sparse_parse_fill_chunk(sparse_header_t *sparse,
102   - chunk_header_t *chunk)
103   -{
104   - unsigned int chunk_data_sz = sparse_get_chunk_data_size(sparse, chunk);
105   -
106   - if (chunk_data_sz != sizeof(uint32_t))
107   - return -EINVAL;
108   -
109   - return 0;
110   -}
111   -
112   -static int sparse_parse_raw_chunk(sparse_header_t *sparse,
113   - chunk_header_t *chunk)
114   -{
115   - unsigned int chunk_data_sz = sparse_get_chunk_data_size(sparse, chunk);
116   -
117   - /* Check if the data size is a multiple of the main block size */
118   - if (chunk_data_sz % sparse->blk_sz)
119   - return -EINVAL;
120   -
121   - /* Check that the chunk size is consistent */
122   - if ((chunk_data_sz / sparse->blk_sz) != chunk->chunk_sz)
123   - return -EINVAL;
124   -
125   - return 0;
126   -}
127   -
128   -static chunk_header_t *sparse_parse_chunk(sparse_header_t *sparse,
129   - void **image)
130   -{
131   - chunk_header_t *chunk = (chunk_header_t *) *image;
132   - int ret;
133   -
134   - debug("=== Chunk Header ===\n");
135   - debug("chunk_type: 0x%x\n", chunk->chunk_type);
136   - debug("chunk_data_sz: 0x%x\n", chunk->chunk_sz);
137   - debug("total_size: 0x%x\n", chunk->total_sz);
138   -
139   - switch (chunk->chunk_type) {
140   - case CHUNK_TYPE_RAW:
141   - ret = sparse_parse_raw_chunk(sparse, chunk);
142   - if (ret)
143   - return NULL;
144   - break;
145   -
146   - case CHUNK_TYPE_FILL:
147   - ret = sparse_parse_fill_chunk(sparse, chunk);
148   - if (ret)
149   - return NULL;
150   - break;
151   -
152   - case CHUNK_TYPE_DONT_CARE:
153   - case CHUNK_TYPE_CRC32:
154   - debug("Ignoring chunk\n");
155   - break;
156   -
157   - default:
158   - printf("%s: Unknown chunk type: %x\n", __func__,
159   - chunk->chunk_type);
160   - return NULL;
161   - }
162   -
163   - *image += sparse->chunk_hdr_sz;
164   -
165   - return chunk;
166   -}
167   -
168   -static int sparse_get_fill_buffer(sparse_header_t *sparse,
169   - chunk_header_t *chunk,
170   - sparse_buffer_t *buffer,
171   - unsigned int blk_sz,
172   - void *data)
173   -{
174   - int i;
175   -
176   - buffer->type = CHUNK_TYPE_FILL;
177   -
178 88 /*
179   - * We create a buffer of one block, and ask it to be
180   - * repeated as many times as needed.
181   - */
182   - buffer->length = blk_sz;
183   - buffer->repeat = (chunk->chunk_sz * sparse->blk_sz) / blk_sz;
184   -
185   - buffer->data = memalign(ARCH_DMA_MINALIGN,
186   - ROUNDUP(blk_sz,
187   - ARCH_DMA_MINALIGN));
188   - if (!buffer->data)
189   - return -ENOMEM;
190   -
191   - for (i = 0; i < (buffer->length / sizeof(uint32_t)); i++)
192   - ((uint32_t *)buffer->data)[i] = *(uint32_t *)(data);
193   -
194   - return 0;
195   -}
196   -
197   -static int sparse_get_raw_buffer(sparse_header_t *sparse,
198   - chunk_header_t *chunk,
199   - sparse_buffer_t *buffer,
200   - unsigned int blk_sz,
201   - void *data)
202   -{
203   - unsigned int chunk_data_sz = sparse_get_chunk_data_size(sparse, chunk);
204   -
205   - buffer->type = CHUNK_TYPE_RAW;
206   - buffer->length = chunk_data_sz;
207   - buffer->data = data;
208   - buffer->repeat = 1;
209   -
210   - return 0;
211   -}
212   -
213   -static sparse_buffer_t *sparse_get_data_buffer(sparse_header_t *sparse,
214   - chunk_header_t *chunk,
215   - unsigned int blk_sz,
216   - void **image)
217   -{
218   - unsigned int chunk_data_sz = sparse_get_chunk_data_size(sparse, chunk);
219   - sparse_buffer_t *buffer;
220   - void *data = *image;
221   - int ret;
222   -
223   - *image += chunk_data_sz;
224   -
225   - if (!sparse_chunk_has_buffer(chunk))
226   - return NULL;
227   -
228   - buffer = calloc(sizeof(sparse_buffer_t), 1);
229   - if (!buffer)
230   - return NULL;
231   -
232   - switch (chunk->chunk_type) {
233   - case CHUNK_TYPE_RAW:
234   - ret = sparse_get_raw_buffer(sparse, chunk, buffer, blk_sz,
235   - data);
236   - if (ret)
237   - return NULL;
238   - break;
239   -
240   - case CHUNK_TYPE_FILL:
241   - ret = sparse_get_fill_buffer(sparse, chunk, buffer, blk_sz,
242   - data);
243   - if (ret)
244   - return NULL;
245   - break;
246   -
247   - default:
248   - return NULL;
249   - }
250   -
251   - debug("=== Buffer ===\n");
252   - debug("length: 0x%x\n", buffer->length);
253   - debug("repeat: 0x%x\n", buffer->repeat);
254   - debug("type: 0x%x\n", buffer->type);
255   - debug("data: 0x%p\n", buffer->data);
256   -
257   - return buffer;
258   -}
259   -
260   -static void sparse_put_data_buffer(sparse_buffer_t *buffer)
261   -{
262   - if (buffer->type == CHUNK_TYPE_FILL)
263   - free(buffer->data);
264   -
265   - free(buffer);
266   -}
267   -
268   -int store_sparse_image(sparse_storage_t *storage,
269   - void *storage_priv, void *data)
270   -{
271   - unsigned int chunk, offset;
272   - sparse_header_t *sparse_header;
273   - chunk_header_t *chunk_header;
274   - sparse_buffer_t *buffer;
275   - uint32_t start;
276   - uint32_t total_blocks = 0;
277   - int i;
278   -
279   - debug("=== Storage ===\n");
280   - debug("name: %s\n", storage->name);
281   - debug("block_size: 0x%x\n", storage->block_sz);
282   - debug("start: 0x%x\n", storage->start);
283   - debug("size: 0x%x\n", storage->size);
284   - debug("write: 0x%p\n", storage->write);
285   - debug("priv: 0x%p\n", storage_priv);
286   -
287   - sparse_header = sparse_parse_header(&data);
288   - if (!sparse_header) {
289   - printf("sparse header issue\n");
290   - return -EINVAL;
291   - }
292   -
293   - /*
294 89 * Verify that the sparse block size is a multiple of our
295 90 * storage backend block size
296 91 */
297   - div_u64_rem(sparse_header->blk_sz, storage->block_sz, &offset);
  92 + div_u64_rem(sparse_header->blk_sz, info->blksz, &offset);
298 93 if (offset) {
299 94 printf("%s: Sparse image block size issue [%u]\n",
300 95 __func__, sparse_header->blk_sz);
301   - return -EINVAL;
  96 + fastboot_fail(response_str, "sparse image block size issue");
  97 + return;
302 98 }
303 99  
304 100 puts("Flashing Sparse Image\n");
305 101  
306 102 /* Start processing chunks */
307   - start = storage->start;
  103 + blk = info->start;
308 104 for (chunk = 0; chunk < sparse_header->total_chunks; chunk++) {
309   - uint32_t blkcnt;
  105 + /* Read and skip over chunk header */
  106 + chunk_header = (chunk_header_t *)data;
  107 + data += sizeof(chunk_header_t);
310 108  
311   - chunk_header = sparse_parse_chunk(sparse_header, &data);
312   - if (!chunk_header) {
313   - printf("Unknown chunk type");
314   - return -EINVAL;
  109 + if (chunk_header->chunk_type != CHUNK_TYPE_RAW) {
  110 + debug("=== Chunk Header ===\n");
  111 + debug("chunk_type: 0x%x\n", chunk_header->chunk_type);
  112 + debug("chunk_data_sz: 0x%x\n", chunk_header->chunk_sz);
  113 + debug("total_size: 0x%x\n", chunk_header->total_sz);
315 114 }
316 115  
317   - /*
318   - * If we have a DONT_CARE type, just skip the blocks
319   - * and go on parsing the rest of the chunks
320   - */
321   - if (chunk_header->chunk_type == CHUNK_TYPE_DONT_CARE) {
322   - blkcnt = sparse_block_size_to_storage(chunk_header->chunk_sz,
323   - storage,
324   - sparse_header);
325   -#ifdef CONFIG_FASTBOOT_FLASH_MMC_DEV
326   - total_blocks += blkcnt;
327   -#endif
328   - continue;
  116 + if (sparse_header->chunk_hdr_sz > sizeof(chunk_header_t)) {
  117 + /*
  118 + * Skip the remaining bytes in a header that is longer
  119 + * than we expected.
  120 + */
  121 + data += (sparse_header->chunk_hdr_sz -
  122 + sizeof(chunk_header_t));
329 123 }
330 124  
331   - /* Retrieve the buffer we're going to write */
332   - buffer = sparse_get_data_buffer(sparse_header, chunk_header,
333   - storage->block_sz, &data);
334   - if (!buffer)
335   - continue;
  125 + chunk_data_sz = sparse_header->blk_sz * chunk_header->chunk_sz;
  126 + blkcnt = chunk_data_sz / info->blksz;
  127 + switch (chunk_header->chunk_type) {
  128 + case CHUNK_TYPE_RAW:
  129 + if (chunk_header->total_sz !=
  130 + (sparse_header->chunk_hdr_sz + chunk_data_sz)) {
  131 + fastboot_fail(response_str,
  132 + "Bogus chunk size for chunk type Raw");
  133 + return;
  134 + }
336 135  
337   - blkcnt = (buffer->length / storage->block_sz) * buffer->repeat;
  136 + if (blk + blkcnt > info->start + info->size) {
  137 + printf(
  138 + "%s: Request would exceed partition size!\n",
  139 + __func__);
  140 + fastboot_fail(response_str,
  141 + "Request would exceed partition size!");
  142 + return;
  143 + }
338 144  
339   - if ((start + total_blocks + blkcnt) >
340   - (storage->start + storage->size)) {
341   - printf("%s: Request would exceed partition size!\n",
342   - __func__);
343   - return -EINVAL;
344   - }
  145 + blks = info->write(info, blk, blkcnt, data);
  146 + /* blks might be > blkcnt (eg. NAND bad-blocks) */
  147 + if (blks < blkcnt) {
  148 + printf("%s: %s" LBAFU " [" LBAFU "]\n",
  149 + __func__, "Write failed, block #",
  150 + blk, blks);
  151 + fastboot_fail(response_str,
  152 + "flash write failure");
  153 + return;
  154 + }
  155 + blk += blks;
  156 + bytes_written += blkcnt * info->blksz;
  157 + total_blocks += chunk_header->chunk_sz;
  158 + data += chunk_data_sz;
  159 + break;
345 160  
346   - for (i = 0; i < buffer->repeat; i++) {
347   - unsigned long buffer_blk_cnt;
348   - int ret;
  161 + case CHUNK_TYPE_FILL:
  162 + if (chunk_header->total_sz !=
  163 + (sparse_header->chunk_hdr_sz + sizeof(uint32_t))) {
  164 + fastboot_fail(response_str,
  165 + "Bogus chunk size for chunk type FILL");
  166 + return;
  167 + }
349 168  
350   - buffer_blk_cnt = buffer->length / storage->block_sz;
  169 + fill_buf = (uint32_t *)
  170 + memalign(ARCH_DMA_MINALIGN,
  171 + ROUNDUP(info->blksz,
  172 + ARCH_DMA_MINALIGN));
  173 + if (!fill_buf) {
  174 + fastboot_fail(response_str,
  175 + "Malloc failed for: CHUNK_TYPE_FILL");
  176 + return;
  177 + }
351 178  
352   - ret = storage->write(storage, storage_priv,
353   - start + total_blocks,
354   - buffer_blk_cnt,
355   - buffer->data);
356   - if (ret < 0) {
357   - printf("%s: Write %d failed %d\n",
358   - __func__, i, ret);
359   - return ret;
  179 + fill_val = *(uint32_t *)data;
  180 + data = (char *)data + sizeof(uint32_t);
  181 +
  182 + for (i = 0; i < (info->blksz / sizeof(fill_val)); i++)
  183 + fill_buf[i] = fill_val;
  184 +
  185 + if (blk + blkcnt > info->start + info->size) {
  186 + printf(
  187 + "%s: Request would exceed partition size!\n",
  188 + __func__);
  189 + fastboot_fail(response_str,
  190 + "Request would exceed partition size!");
  191 + return;
360 192 }
361 193  
362   - total_blocks += ret;
363   - }
  194 + for (i = 0; i < blkcnt; i++) {
  195 + blks = info->write(info, blk, 1, fill_buf);
  196 + /* blks might be > 1 (eg. NAND bad-blocks) */
  197 + if (blks < 1) {
  198 + printf("%s: %s, block # " LBAFU "\n",
  199 + __func__, "Write failed", blk);
  200 + fastboot_fail(response_str,
  201 + "flash write failure");
  202 + free(fill_buf);
  203 + return;
  204 + }
  205 + blk += blks;
  206 + }
  207 + bytes_written += blkcnt * info->blksz;
  208 + total_blocks += chunk_data_sz / sparse_header->blk_sz;
  209 + free(fill_buf);
  210 + break;
364 211  
365   - sparse_put_data_buffer(buffer);
  212 + case CHUNK_TYPE_DONT_CARE:
  213 +#ifdef CONFIG_FASTBOOT_FLASH_MMC_DEV
  214 + blk += blkcnt;
  215 + total_blocks += chunk_header->chunk_sz;
  216 +#endif
  217 + break;
  218 +
  219 + case CHUNK_TYPE_CRC32:
  220 + if (chunk_header->total_sz !=
  221 + sparse_header->chunk_hdr_sz) {
  222 + fastboot_fail(response_str,
  223 + "Bogus chunk size for chunk type Dont Care");
  224 + return;
  225 + }
  226 + total_blocks += chunk_header->chunk_sz;
  227 + data += chunk_data_sz;
  228 + break;
  229 +
  230 + default:
  231 + printf("%s: Unknown chunk type: %x\n", __func__,
  232 + chunk_header->chunk_type);
  233 + fastboot_fail(response_str, "Unknown chunk type");
  234 + return;
  235 + }
366 236 }
367 237  
368 238 debug("Wrote %d blocks, expected to write %d blocks\n",
369   - total_blocks,
370   - sparse_block_size_to_storage(sparse_header->total_blks,
371   - storage, sparse_header));
372   - printf("........ wrote %d blocks to '%s'\n", total_blocks,
373   - storage->name);
  239 + total_blocks, sparse_header->total_blks);
  240 + printf("........ wrote %u bytes to '%s'\n", bytes_written, part_name);
374 241  
375   - if (total_blocks !=
376   - sparse_block_size_to_storage(sparse_header->total_blks,
377   - storage, sparse_header)) {
378   - printf("sparse image write failure\n");
379   - return -EIO;
380   - }
  242 + if (total_blocks != sparse_header->total_blks)
  243 + fastboot_fail(response_str, "sparse image write failure");
  244 + else
  245 + fastboot_okay(response_str, "");
381 246  
382   - return 0;
  247 + return;
383 248 }
include/image-sparse.h
... ... @@ -9,16 +9,17 @@
9 9  
10 10 #define ROUNDUP(x, y) (((x) + ((y) - 1)) & ~((y) - 1))
11 11  
12   -typedef struct sparse_storage {
13   - unsigned int block_sz;
14   - unsigned int start;
15   - unsigned int size;
16   - const char *name;
  12 +struct sparse_storage {
  13 + lbaint_t blksz;
  14 + lbaint_t start;
  15 + lbaint_t size;
  16 + void *priv;
17 17  
18   - int (*write)(struct sparse_storage *storage, void *priv,
19   - unsigned int offset, unsigned int size,
20   - char *data);
21   -} sparse_storage_t;
  18 + lbaint_t (*write)(struct sparse_storage *info,
  19 + lbaint_t blk,
  20 + lbaint_t blkcnt,
  21 + const void *buffer);
  22 +};
22 23  
23 24 static inline int is_sparse_image(void *buf)
24 25 {
... ... @@ -31,6 +32,6 @@
31 32 return 0;
32 33 }
33 34  
34   -int store_sparse_image(sparse_storage_t *storage, void *storage_priv,
35   - void *data);
  35 +void write_sparse_image(struct sparse_storage *info, const char *part_name,
  36 + void *data, unsigned sz, char *response_str);