Commit 3d4ef38de2f65e9d122e1c40221f303ade0eac97

Authored by Maxime Ripard
Committed by Tom Rini
1 parent 6fb77c48e4

sparse: Rename the file and header

The Android sparse image format is currently supported through a file
called aboot, which isn't really such a great name, since the sparse image
format is only used for transferring data with fastboot.

Rename the file and header to a file called "sparse", which also makes it
consistent with the header defining the image structures.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
Reviewed-by: Tom Rini <trini@konsulko.com>

Showing 7 changed files with 431 additions and 431 deletions Side-by-side Diff

... ... @@ -277,7 +277,7 @@
277 277  
278 278 # This option is not just y/n - it can have a numeric value
279 279 ifdef CONFIG_FASTBOOT_FLASH
280   -obj-y += aboot.o
  280 +obj-y += image-sparse.o
281 281 ifdef CONFIG_FASTBOOT_FLASH_MMC_DEV
282 282 obj-y += fb_mmc.o
283 283 endif
common/aboot.c
1   -/*
2   - * Copyright (c) 2009, Google Inc.
3   - * All rights reserved.
4   - *
5   - * Copyright (c) 2009-2014, The Linux Foundation. All rights reserved.
6   - * Portions Copyright 2014 Broadcom Corporation.
7   - *
8   - * Redistribution and use in source and binary forms, with or without
9   - * modification, are permitted provided that the following conditions are met:
10   - * * Redistributions of source code must retain the above copyright
11   - * notice, this list of conditions and the following disclaimer.
12   - * * Redistributions in binary form must reproduce the above copyright
13   - * notice, this list of conditions and the following disclaimer in the
14   - * documentation and/or other materials provided with the distribution.
15   - * * Neither the name of The Linux Foundation nor
16   - * the names of its contributors may be used to endorse or promote
17   - * products derived from this software without specific prior written
18   - * permission.
19   - *
20   - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21   - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22   - * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23   - * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24   - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25   - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26   - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
27   - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28   - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29   - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
30   - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31   - *
32   - * NOTE:
33   - * Although it is very similar, this license text is not identical
34   - * to the "BSD-3-Clause", therefore, DO NOT MODIFY THIS LICENSE TEXT!
35   - */
36   -
37   -#include <config.h>
38   -#include <common.h>
39   -#include <aboot.h>
40   -#include <div64.h>
41   -#include <errno.h>
42   -#include <malloc.h>
43   -#include <part.h>
44   -#include <sparse_format.h>
45   -
46   -#include <linux/math64.h>
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 uint32_t last_offset;
56   -
57   -static unsigned int sparse_get_chunk_data_size(sparse_header_t *sparse,
58   - chunk_header_t *chunk)
59   -{
60   - return chunk->total_sz - sparse->chunk_hdr_sz;
61   -}
62   -
63   -static unsigned int sparse_block_size_to_storage(unsigned int size,
64   - sparse_storage_t *storage,
65   - sparse_header_t *sparse)
66   -{
67   - return size * sparse->blk_sz / storage->block_sz;
68   -}
69   -
70   -static bool sparse_chunk_has_buffer(chunk_header_t *chunk)
71   -{
72   - switch (chunk->chunk_type) {
73   - case CHUNK_TYPE_RAW:
74   - case CHUNK_TYPE_FILL:
75   - return true;
76   -
77   - default:
78   - return false;
79   - }
80   -}
81   -
82   -static sparse_header_t *sparse_parse_header(void **data)
83   -{
84   - /* Read and skip over sparse image header */
85   - sparse_header_t *sparse_header = (sparse_header_t *) *data;
86   -
87   - *data += sparse_header->file_hdr_sz;
88   -
89   - debug("=== Sparse Image Header ===\n");
90   - debug("magic: 0x%x\n", sparse_header->magic);
91   - debug("major_version: 0x%x\n", sparse_header->major_version);
92   - debug("minor_version: 0x%x\n", sparse_header->minor_version);
93   - debug("file_hdr_sz: %d\n", sparse_header->file_hdr_sz);
94   - debug("chunk_hdr_sz: %d\n", sparse_header->chunk_hdr_sz);
95   - debug("blk_sz: %d\n", sparse_header->blk_sz);
96   - debug("total_blks: %d\n", sparse_header->total_blks);
97   - debug("total_chunks: %d\n", sparse_header->total_chunks);
98   -
99   - return sparse_header;
100   -}
101   -
102   -static int sparse_parse_fill_chunk(sparse_header_t *sparse,
103   - chunk_header_t *chunk)
104   -{
105   - unsigned int chunk_data_sz = sparse_get_chunk_data_size(sparse, chunk);
106   -
107   - if (chunk_data_sz != sizeof(uint32_t))
108   - return -EINVAL;
109   -
110   - return 0;
111   -}
112   -
113   -static int sparse_parse_raw_chunk(sparse_header_t *sparse,
114   - chunk_header_t *chunk)
115   -{
116   - unsigned int chunk_data_sz = sparse_get_chunk_data_size(sparse, chunk);
117   -
118   - /* Check if the data size is a multiple of the main block size */
119   - if (chunk_data_sz % sparse->blk_sz)
120   - return -EINVAL;
121   -
122   - /* Check that the chunk size is consistent */
123   - if ((chunk_data_sz / sparse->blk_sz) != chunk->chunk_sz)
124   - return -EINVAL;
125   -
126   - return 0;
127   -}
128   -
129   -static chunk_header_t *sparse_parse_chunk(sparse_header_t *sparse,
130   - void **image)
131   -{
132   - chunk_header_t *chunk = (chunk_header_t *) *image;
133   - int ret;
134   -
135   - debug("=== Chunk Header ===\n");
136   - debug("chunk_type: 0x%x\n", chunk->chunk_type);
137   - debug("chunk_data_sz: 0x%x\n", chunk->chunk_sz);
138   - debug("total_size: 0x%x\n", chunk->total_sz);
139   -
140   - switch (chunk->chunk_type) {
141   - case CHUNK_TYPE_RAW:
142   - ret = sparse_parse_raw_chunk(sparse, chunk);
143   - if (ret)
144   - return NULL;
145   - break;
146   -
147   - case CHUNK_TYPE_FILL:
148   - ret = sparse_parse_fill_chunk(sparse, chunk);
149   - if (ret)
150   - return NULL;
151   - break;
152   -
153   - case CHUNK_TYPE_DONT_CARE:
154   - case CHUNK_TYPE_CRC32:
155   - debug("Ignoring chunk\n");
156   - break;
157   -
158   - default:
159   - printf("%s: Unknown chunk type: %x\n", __func__,
160   - chunk->chunk_type);
161   - return NULL;
162   - }
163   -
164   - *image += sparse->chunk_hdr_sz;
165   -
166   - return chunk;
167   -}
168   -
169   -static int sparse_get_fill_buffer(sparse_header_t *sparse,
170   - chunk_header_t *chunk,
171   - sparse_buffer_t *buffer,
172   - unsigned int blk_sz,
173   - void *data)
174   -{
175   - int i;
176   -
177   - buffer->type = CHUNK_TYPE_FILL;
178   -
179   - /*
180   - * We create a buffer of one block, and ask it to be
181   - * repeated as many times as needed.
182   - */
183   - buffer->length = blk_sz;
184   - buffer->repeat = (chunk->chunk_sz * sparse->blk_sz) / blk_sz;
185   -
186   - buffer->data = memalign(ARCH_DMA_MINALIGN,
187   - ROUNDUP(blk_sz,
188   - ARCH_DMA_MINALIGN));
189   - if (!buffer->data)
190   - return -ENOMEM;
191   -
192   - for (i = 0; i < (buffer->length / sizeof(uint32_t)); i++)
193   - ((uint32_t *)buffer->data)[i] = *(uint32_t *)(data);
194   -
195   - return 0;
196   -}
197   -
198   -static int sparse_get_raw_buffer(sparse_header_t *sparse,
199   - chunk_header_t *chunk,
200   - sparse_buffer_t *buffer,
201   - unsigned int blk_sz,
202   - void *data)
203   -{
204   - unsigned int chunk_data_sz = sparse_get_chunk_data_size(sparse, chunk);
205   -
206   - buffer->type = CHUNK_TYPE_RAW;
207   - buffer->length = chunk_data_sz;
208   - buffer->data = data;
209   - buffer->repeat = 1;
210   -
211   - return 0;
212   -}
213   -
214   -static sparse_buffer_t *sparse_get_data_buffer(sparse_header_t *sparse,
215   - chunk_header_t *chunk,
216   - unsigned int blk_sz,
217   - void **image)
218   -{
219   - unsigned int chunk_data_sz = sparse_get_chunk_data_size(sparse, chunk);
220   - sparse_buffer_t *buffer;
221   - void *data = *image;
222   - int ret;
223   -
224   - *image += chunk_data_sz;
225   -
226   - if (!sparse_chunk_has_buffer(chunk))
227   - return NULL;
228   -
229   - buffer = calloc(sizeof(sparse_buffer_t), 1);
230   - if (!buffer)
231   - return NULL;
232   -
233   - switch (chunk->chunk_type) {
234   - case CHUNK_TYPE_RAW:
235   - ret = sparse_get_raw_buffer(sparse, chunk, buffer, blk_sz,
236   - data);
237   - if (ret)
238   - return NULL;
239   - break;
240   -
241   - case CHUNK_TYPE_FILL:
242   - ret = sparse_get_fill_buffer(sparse, chunk, buffer, blk_sz,
243   - data);
244   - if (ret)
245   - return NULL;
246   - break;
247   -
248   - default:
249   - return NULL;
250   - }
251   -
252   - debug("=== Buffer ===\n");
253   - debug("length: 0x%x\n", buffer->length);
254   - debug("repeat: 0x%x\n", buffer->repeat);
255   - debug("type: 0x%x\n", buffer->type);
256   - debug("data: 0x%p\n", buffer->data);
257   -
258   - return buffer;
259   -}
260   -
261   -static void sparse_put_data_buffer(sparse_buffer_t *buffer)
262   -{
263   - if (buffer->type == CHUNK_TYPE_FILL)
264   - free(buffer->data);
265   -
266   - free(buffer);
267   -}
268   -
269   -int store_sparse_image(sparse_storage_t *storage, void *storage_priv,
270   - unsigned int session_id, void *data)
271   -{
272   - unsigned int chunk, offset;
273   - sparse_header_t *sparse_header;
274   - chunk_header_t *chunk_header;
275   - sparse_buffer_t *buffer;
276   - uint32_t start;
277   - uint32_t total_blocks = 0;
278   - uint32_t skipped = 0;
279   - int i;
280   -
281   - debug("=== Storage ===\n");
282   - debug("name: %s\n", storage->name);
283   - debug("block_size: 0x%x\n", storage->block_sz);
284   - debug("start: 0x%x\n", storage->start);
285   - debug("size: 0x%x\n", storage->size);
286   - debug("write: 0x%p\n", storage->write);
287   - debug("priv: 0x%p\n", storage_priv);
288   -
289   - sparse_header = sparse_parse_header(&data);
290   - if (!sparse_header) {
291   - printf("sparse header issue\n");
292   - return -EINVAL;
293   - }
294   -
295   - /*
296   - * Verify that the sparse block size is a multiple of our
297   - * storage backend block size
298   - */
299   - div_u64_rem(sparse_header->blk_sz, storage->block_sz, &offset);
300   - if (offset) {
301   - printf("%s: Sparse image block size issue [%u]\n",
302   - __func__, sparse_header->blk_sz);
303   - return -EINVAL;
304   - }
305   -
306   - /*
307   - * If it's a new flashing session, start at the beginning of
308   - * the partition. If not, then simply resume where we were.
309   - */
310   - if (session_id > 0)
311   - start = last_offset;
312   - else
313   - start = storage->start;
314   -
315   - printf("Flashing sparse image on partition %s at offset 0x%x (ID: %d)\n",
316   - storage->name, start * storage->block_sz, session_id);
317   -
318   - /* Start processing chunks */
319   - for (chunk = 0; chunk < sparse_header->total_chunks; chunk++) {
320   - uint32_t blkcnt;
321   -
322   - chunk_header = sparse_parse_chunk(sparse_header, &data);
323   - if (!chunk_header) {
324   - printf("Unknown chunk type");
325   - return -EINVAL;
326   - }
327   -
328   - /*
329   - * If we have a DONT_CARE type, just skip the blocks
330   - * and go on parsing the rest of the chunks
331   - */
332   - if (chunk_header->chunk_type == CHUNK_TYPE_DONT_CARE) {
333   - skipped += sparse_block_size_to_storage(chunk_header->chunk_sz,
334   - storage,
335   - sparse_header);
336   - continue;
337   - }
338   -
339   - /* Retrieve the buffer we're going to write */
340   - buffer = sparse_get_data_buffer(sparse_header, chunk_header,
341   - storage->block_sz, &data);
342   - if (!buffer)
343   - continue;
344   -
345   - blkcnt = (buffer->length / storage->block_sz) * buffer->repeat;
346   -
347   - if ((start + total_blocks + blkcnt) >
348   - (storage->start + storage->size)) {
349   - printf("%s: Request would exceed partition size!\n",
350   - __func__);
351   - return -EINVAL;
352   - }
353   -
354   - for (i = 0; i < buffer->repeat; i++) {
355   - unsigned long buffer_blk_cnt;
356   - int ret;
357   -
358   - buffer_blk_cnt = buffer->length / storage->block_sz;
359   -
360   - ret = storage->write(storage, storage_priv,
361   - start + total_blocks,
362   - buffer_blk_cnt,
363   - buffer->data);
364   - if (ret < 0) {
365   - printf("%s: Write %d failed %d\n",
366   - __func__, i, ret);
367   - return ret;
368   - }
369   -
370   - total_blocks += ret;
371   - }
372   -
373   - sparse_put_data_buffer(buffer);
374   - }
375   -
376   - debug("Wrote %d blocks, skipped %d, expected to write %d blocks\n",
377   - total_blocks, skipped,
378   - sparse_block_size_to_storage(sparse_header->total_blks,
379   - storage, sparse_header));
380   - printf("........ wrote %d blocks to '%s'\n", total_blocks,
381   - storage->name);
382   -
383   - if ((total_blocks + skipped) !=
384   - sparse_block_size_to_storage(sparse_header->total_blks,
385   - storage, sparse_header)) {
386   - printf("sparse image write failure\n");
387   - return -EIO;
388   - }
389   -
390   - last_offset = start + total_blocks;
391   -
392   - return 0;
393   -}
... ... @@ -9,8 +9,8 @@
9 9 #include <errno.h>
10 10 #include <fastboot.h>
11 11 #include <fb_mmc.h>
  12 +#include <image-sparse.h>
12 13 #include <part.h>
13   -#include <aboot.h>
14 14 #include <sparse_format.h>
15 15 #include <mmc.h>
16 16  
... ... @@ -8,8 +8,8 @@
8 8 #include <config.h>
9 9 #include <common.h>
10 10  
11   -#include <aboot.h>
12 11 #include <fastboot.h>
  12 +#include <image-sparse.h>
13 13 #include <sparse_format.h>
14 14  
15 15 #include <linux/mtd/mtd.h>
common/image-sparse.c
  1 +/*
  2 + * Copyright (c) 2009, Google Inc.
  3 + * All rights reserved.
  4 + *
  5 + * Copyright (c) 2009-2014, The Linux Foundation. All rights reserved.
  6 + * Portions Copyright 2014 Broadcom Corporation.
  7 + *
  8 + * Redistribution and use in source and binary forms, with or without
  9 + * modification, are permitted provided that the following conditions are met:
  10 + * * Redistributions of source code must retain the above copyright
  11 + * notice, this list of conditions and the following disclaimer.
  12 + * * Redistributions in binary form must reproduce the above copyright
  13 + * notice, this list of conditions and the following disclaimer in the
  14 + * documentation and/or other materials provided with the distribution.
  15 + * * Neither the name of The Linux Foundation nor
  16 + * the names of its contributors may be used to endorse or promote
  17 + * products derived from this software without specific prior written
  18 + * permission.
  19 + *
  20 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  21 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  22 + * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  23 + * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  24 + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  25 + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  26 + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
  27 + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  28 + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
  29 + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
  30 + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  31 + *
  32 + * NOTE:
  33 + * Although it is very similar, this license text is not identical
  34 + * to the "BSD-3-Clause", therefore, DO NOT MODIFY THIS LICENSE TEXT!
  35 + */
  36 +
  37 +#include <config.h>
  38 +#include <common.h>
  39 +#include <div64.h>
  40 +#include <errno.h>
  41 +#include <image-sparse.h>
  42 +#include <malloc.h>
  43 +#include <part.h>
  44 +#include <sparse_format.h>
  45 +
  46 +#include <linux/math64.h>
  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 uint32_t last_offset;
  56 +
  57 +static unsigned int sparse_get_chunk_data_size(sparse_header_t *sparse,
  58 + chunk_header_t *chunk)
  59 +{
  60 + return chunk->total_sz - sparse->chunk_hdr_sz;
  61 +}
  62 +
  63 +static unsigned int sparse_block_size_to_storage(unsigned int size,
  64 + sparse_storage_t *storage,
  65 + sparse_header_t *sparse)
  66 +{
  67 + return size * sparse->blk_sz / storage->block_sz;
  68 +}
  69 +
  70 +static bool sparse_chunk_has_buffer(chunk_header_t *chunk)
  71 +{
  72 + switch (chunk->chunk_type) {
  73 + case CHUNK_TYPE_RAW:
  74 + case CHUNK_TYPE_FILL:
  75 + return true;
  76 +
  77 + default:
  78 + return false;
  79 + }
  80 +}
  81 +
  82 +static sparse_header_t *sparse_parse_header(void **data)
  83 +{
  84 + /* Read and skip over sparse image header */
  85 + sparse_header_t *sparse_header = (sparse_header_t *) *data;
  86 +
  87 + *data += sparse_header->file_hdr_sz;
  88 +
  89 + debug("=== Sparse Image Header ===\n");
  90 + debug("magic: 0x%x\n", sparse_header->magic);
  91 + debug("major_version: 0x%x\n", sparse_header->major_version);
  92 + debug("minor_version: 0x%x\n", sparse_header->minor_version);
  93 + debug("file_hdr_sz: %d\n", sparse_header->file_hdr_sz);
  94 + debug("chunk_hdr_sz: %d\n", sparse_header->chunk_hdr_sz);
  95 + debug("blk_sz: %d\n", sparse_header->blk_sz);
  96 + debug("total_blks: %d\n", sparse_header->total_blks);
  97 + debug("total_chunks: %d\n", sparse_header->total_chunks);
  98 +
  99 + return sparse_header;
  100 +}
  101 +
  102 +static int sparse_parse_fill_chunk(sparse_header_t *sparse,
  103 + chunk_header_t *chunk)
  104 +{
  105 + unsigned int chunk_data_sz = sparse_get_chunk_data_size(sparse, chunk);
  106 +
  107 + if (chunk_data_sz != sizeof(uint32_t))
  108 + return -EINVAL;
  109 +
  110 + return 0;
  111 +}
  112 +
  113 +static int sparse_parse_raw_chunk(sparse_header_t *sparse,
  114 + chunk_header_t *chunk)
  115 +{
  116 + unsigned int chunk_data_sz = sparse_get_chunk_data_size(sparse, chunk);
  117 +
  118 + /* Check if the data size is a multiple of the main block size */
  119 + if (chunk_data_sz % sparse->blk_sz)
  120 + return -EINVAL;
  121 +
  122 + /* Check that the chunk size is consistent */
  123 + if ((chunk_data_sz / sparse->blk_sz) != chunk->chunk_sz)
  124 + return -EINVAL;
  125 +
  126 + return 0;
  127 +}
  128 +
  129 +static chunk_header_t *sparse_parse_chunk(sparse_header_t *sparse,
  130 + void **image)
  131 +{
  132 + chunk_header_t *chunk = (chunk_header_t *) *image;
  133 + int ret;
  134 +
  135 + debug("=== Chunk Header ===\n");
  136 + debug("chunk_type: 0x%x\n", chunk->chunk_type);
  137 + debug("chunk_data_sz: 0x%x\n", chunk->chunk_sz);
  138 + debug("total_size: 0x%x\n", chunk->total_sz);
  139 +
  140 + switch (chunk->chunk_type) {
  141 + case CHUNK_TYPE_RAW:
  142 + ret = sparse_parse_raw_chunk(sparse, chunk);
  143 + if (ret)
  144 + return NULL;
  145 + break;
  146 +
  147 + case CHUNK_TYPE_FILL:
  148 + ret = sparse_parse_fill_chunk(sparse, chunk);
  149 + if (ret)
  150 + return NULL;
  151 + break;
  152 +
  153 + case CHUNK_TYPE_DONT_CARE:
  154 + case CHUNK_TYPE_CRC32:
  155 + debug("Ignoring chunk\n");
  156 + break;
  157 +
  158 + default:
  159 + printf("%s: Unknown chunk type: %x\n", __func__,
  160 + chunk->chunk_type);
  161 + return NULL;
  162 + }
  163 +
  164 + *image += sparse->chunk_hdr_sz;
  165 +
  166 + return chunk;
  167 +}
  168 +
  169 +static int sparse_get_fill_buffer(sparse_header_t *sparse,
  170 + chunk_header_t *chunk,
  171 + sparse_buffer_t *buffer,
  172 + unsigned int blk_sz,
  173 + void *data)
  174 +{
  175 + int i;
  176 +
  177 + buffer->type = CHUNK_TYPE_FILL;
  178 +
  179 + /*
  180 + * We create a buffer of one block, and ask it to be
  181 + * repeated as many times as needed.
  182 + */
  183 + buffer->length = blk_sz;
  184 + buffer->repeat = (chunk->chunk_sz * sparse->blk_sz) / blk_sz;
  185 +
  186 + buffer->data = memalign(ARCH_DMA_MINALIGN,
  187 + ROUNDUP(blk_sz,
  188 + ARCH_DMA_MINALIGN));
  189 + if (!buffer->data)
  190 + return -ENOMEM;
  191 +
  192 + for (i = 0; i < (buffer->length / sizeof(uint32_t)); i++)
  193 + ((uint32_t *)buffer->data)[i] = *(uint32_t *)(data);
  194 +
  195 + return 0;
  196 +}
  197 +
  198 +static int sparse_get_raw_buffer(sparse_header_t *sparse,
  199 + chunk_header_t *chunk,
  200 + sparse_buffer_t *buffer,
  201 + unsigned int blk_sz,
  202 + void *data)
  203 +{
  204 + unsigned int chunk_data_sz = sparse_get_chunk_data_size(sparse, chunk);
  205 +
  206 + buffer->type = CHUNK_TYPE_RAW;
  207 + buffer->length = chunk_data_sz;
  208 + buffer->data = data;
  209 + buffer->repeat = 1;
  210 +
  211 + return 0;
  212 +}
  213 +
  214 +static sparse_buffer_t *sparse_get_data_buffer(sparse_header_t *sparse,
  215 + chunk_header_t *chunk,
  216 + unsigned int blk_sz,
  217 + void **image)
  218 +{
  219 + unsigned int chunk_data_sz = sparse_get_chunk_data_size(sparse, chunk);
  220 + sparse_buffer_t *buffer;
  221 + void *data = *image;
  222 + int ret;
  223 +
  224 + *image += chunk_data_sz;
  225 +
  226 + if (!sparse_chunk_has_buffer(chunk))
  227 + return NULL;
  228 +
  229 + buffer = calloc(sizeof(sparse_buffer_t), 1);
  230 + if (!buffer)
  231 + return NULL;
  232 +
  233 + switch (chunk->chunk_type) {
  234 + case CHUNK_TYPE_RAW:
  235 + ret = sparse_get_raw_buffer(sparse, chunk, buffer, blk_sz,
  236 + data);
  237 + if (ret)
  238 + return NULL;
  239 + break;
  240 +
  241 + case CHUNK_TYPE_FILL:
  242 + ret = sparse_get_fill_buffer(sparse, chunk, buffer, blk_sz,
  243 + data);
  244 + if (ret)
  245 + return NULL;
  246 + break;
  247 +
  248 + default:
  249 + return NULL;
  250 + }
  251 +
  252 + debug("=== Buffer ===\n");
  253 + debug("length: 0x%x\n", buffer->length);
  254 + debug("repeat: 0x%x\n", buffer->repeat);
  255 + debug("type: 0x%x\n", buffer->type);
  256 + debug("data: 0x%p\n", buffer->data);
  257 +
  258 + return buffer;
  259 +}
  260 +
  261 +static void sparse_put_data_buffer(sparse_buffer_t *buffer)
  262 +{
  263 + if (buffer->type == CHUNK_TYPE_FILL)
  264 + free(buffer->data);
  265 +
  266 + free(buffer);
  267 +}
  268 +
  269 +int store_sparse_image(sparse_storage_t *storage, void *storage_priv,
  270 + unsigned int session_id, void *data)
  271 +{
  272 + unsigned int chunk, offset;
  273 + sparse_header_t *sparse_header;
  274 + chunk_header_t *chunk_header;
  275 + sparse_buffer_t *buffer;
  276 + uint32_t start;
  277 + uint32_t total_blocks = 0;
  278 + uint32_t skipped = 0;
  279 + int i;
  280 +
  281 + debug("=== Storage ===\n");
  282 + debug("name: %s\n", storage->name);
  283 + debug("block_size: 0x%x\n", storage->block_sz);
  284 + debug("start: 0x%x\n", storage->start);
  285 + debug("size: 0x%x\n", storage->size);
  286 + debug("write: 0x%p\n", storage->write);
  287 + debug("priv: 0x%p\n", storage_priv);
  288 +
  289 + sparse_header = sparse_parse_header(&data);
  290 + if (!sparse_header) {
  291 + printf("sparse header issue\n");
  292 + return -EINVAL;
  293 + }
  294 +
  295 + /*
  296 + * Verify that the sparse block size is a multiple of our
  297 + * storage backend block size
  298 + */
  299 + div_u64_rem(sparse_header->blk_sz, storage->block_sz, &offset);
  300 + if (offset) {
  301 + printf("%s: Sparse image block size issue [%u]\n",
  302 + __func__, sparse_header->blk_sz);
  303 + return -EINVAL;
  304 + }
  305 +
  306 + /*
  307 + * If it's a new flashing session, start at the beginning of
  308 + * the partition. If not, then simply resume where we were.
  309 + */
  310 + if (session_id > 0)
  311 + start = last_offset;
  312 + else
  313 + start = storage->start;
  314 +
  315 + printf("Flashing sparse image on partition %s at offset 0x%x (ID: %d)\n",
  316 + storage->name, start * storage->block_sz, session_id);
  317 +
  318 + /* Start processing chunks */
  319 + for (chunk = 0; chunk < sparse_header->total_chunks; chunk++) {
  320 + uint32_t blkcnt;
  321 +
  322 + chunk_header = sparse_parse_chunk(sparse_header, &data);
  323 + if (!chunk_header) {
  324 + printf("Unknown chunk type");
  325 + return -EINVAL;
  326 + }
  327 +
  328 + /*
  329 + * If we have a DONT_CARE type, just skip the blocks
  330 + * and go on parsing the rest of the chunks
  331 + */
  332 + if (chunk_header->chunk_type == CHUNK_TYPE_DONT_CARE) {
  333 + skipped += sparse_block_size_to_storage(chunk_header->chunk_sz,
  334 + storage,
  335 + sparse_header);
  336 + continue;
  337 + }
  338 +
  339 + /* Retrieve the buffer we're going to write */
  340 + buffer = sparse_get_data_buffer(sparse_header, chunk_header,
  341 + storage->block_sz, &data);
  342 + if (!buffer)
  343 + continue;
  344 +
  345 + blkcnt = (buffer->length / storage->block_sz) * buffer->repeat;
  346 +
  347 + if ((start + total_blocks + blkcnt) >
  348 + (storage->start + storage->size)) {
  349 + printf("%s: Request would exceed partition size!\n",
  350 + __func__);
  351 + return -EINVAL;
  352 + }
  353 +
  354 + for (i = 0; i < buffer->repeat; i++) {
  355 + unsigned long buffer_blk_cnt;
  356 + int ret;
  357 +
  358 + buffer_blk_cnt = buffer->length / storage->block_sz;
  359 +
  360 + ret = storage->write(storage, storage_priv,
  361 + start + total_blocks,
  362 + buffer_blk_cnt,
  363 + buffer->data);
  364 + if (ret < 0) {
  365 + printf("%s: Write %d failed %d\n",
  366 + __func__, i, ret);
  367 + return ret;
  368 + }
  369 +
  370 + total_blocks += ret;
  371 + }
  372 +
  373 + sparse_put_data_buffer(buffer);
  374 + }
  375 +
  376 + debug("Wrote %d blocks, skipped %d, expected to write %d blocks\n",
  377 + total_blocks, skipped,
  378 + sparse_block_size_to_storage(sparse_header->total_blks,
  379 + storage, sparse_header));
  380 + printf("........ wrote %d blocks to '%s'\n", total_blocks,
  381 + storage->name);
  382 +
  383 + if ((total_blocks + skipped) !=
  384 + sparse_block_size_to_storage(sparse_header->total_blks,
  385 + storage, sparse_header)) {
  386 + printf("sparse image write failure\n");
  387 + return -EIO;
  388 + }
  389 +
  390 + last_offset = start + total_blocks;
  391 +
  392 + return 0;
  393 +}
include/aboot.h
1   -/*
2   - * Copyright 2014 Broadcom Corporation.
3   - *
4   - * SPDX-License-Identifier: GPL-2.0+
5   - */
6   -
7   -#include <part.h>
8   -#include <sparse_format.h>
9   -
10   -#define ROUNDUP(x, y) (((x) + ((y) - 1)) & ~((y) - 1))
11   -
12   -typedef struct sparse_storage {
13   - unsigned int block_sz;
14   - unsigned int start;
15   - unsigned int size;
16   - const char *name;
17   -
18   - int (*write)(struct sparse_storage *storage, void *priv,
19   - unsigned int offset, unsigned int size,
20   - char *data);
21   -} sparse_storage_t;
22   -
23   -static inline int is_sparse_image(void *buf)
24   -{
25   - sparse_header_t *s_header = (sparse_header_t *)buf;
26   -
27   - if ((le32_to_cpu(s_header->magic) == SPARSE_HEADER_MAGIC) &&
28   - (le16_to_cpu(s_header->major_version) == 1))
29   - return 1;
30   -
31   - return 0;
32   -}
33   -
34   -int store_sparse_image(sparse_storage_t *storage, void *storage_priv,
35   - unsigned int session_id, void *data);
include/image-sparse.h
  1 +/*
  2 + * Copyright 2014 Broadcom Corporation.
  3 + *
  4 + * SPDX-License-Identifier: GPL-2.0+
  5 + */
  6 +
  7 +#include <part.h>
  8 +#include <sparse_format.h>
  9 +
  10 +#define ROUNDUP(x, y) (((x) + ((y) - 1)) & ~((y) - 1))
  11 +
  12 +typedef struct sparse_storage {
  13 + unsigned int block_sz;
  14 + unsigned int start;
  15 + unsigned int size;
  16 + const char *name;
  17 +
  18 + int (*write)(struct sparse_storage *storage, void *priv,
  19 + unsigned int offset, unsigned int size,
  20 + char *data);
  21 +} sparse_storage_t;
  22 +
  23 +static inline int is_sparse_image(void *buf)
  24 +{
  25 + sparse_header_t *s_header = (sparse_header_t *)buf;
  26 +
  27 + if ((le32_to_cpu(s_header->magic) == SPARSE_HEADER_MAGIC) &&
  28 + (le16_to_cpu(s_header->major_version) == 1))
  29 + return 1;
  30 +
  31 + return 0;
  32 +}
  33 +
  34 +int store_sparse_image(sparse_storage_t *storage, void *storage_priv,
  35 + unsigned int session_id, void *data);