Blame view

common/image-sparse.c 7.86 KB
b4e4bbe5a   Steve Rae   add code to handl...
1
2
3
4
5
  /*
   * Copyright (c) 2009, Google Inc.
   * All rights reserved.
   *
   * Copyright (c) 2009-2014, The Linux Foundation. All rights reserved.
e6ca1ad60   Steve Rae   implement the And...
6
   * Portions Copyright 2014 Broadcom Corporation.
b4e4bbe5a   Steve Rae   add code to handl...
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions are met:
   *     * Redistributions of source code must retain the above copyright
   *       notice, this list of conditions and the following disclaimer.
   *     * Redistributions in binary form must reproduce the above copyright
   *       notice, this list of conditions and the following disclaimer in the
   *       documentation and/or other materials provided with the distribution.
   *     * Neither the name of The Linux Foundation nor
   *       the names of its contributors may be used to endorse or promote
   *       products derived from this software without specific prior written
   *       permission.
   *
   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
   * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
   * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
   * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
   * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
   * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
   * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
   * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
   * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
   * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   *
1c39d856d   Steve Rae   cleanup code whic...
32
33
34
   * NOTE:
   *   Although it is very similar, this license text is not identical
   *   to the "BSD-3-Clause", therefore, DO NOT MODIFY THIS LICENSE TEXT!
b4e4bbe5a   Steve Rae   add code to handl...
35
   */
e6ca1ad60   Steve Rae   implement the And...
36
37
  #include <config.h>
  #include <common.h>
3d4ef38de   Maxime Ripard   sparse: Rename th...
38
  #include <image-sparse.h>
cc0f08cd3   Steve Rae   fastboot: sparse:...
39
  #include <div64.h>
e6ca1ad60   Steve Rae   implement the And...
40
41
42
  #include <malloc.h>
  #include <part.h>
  #include <sparse_format.h>
cc0f08cd3   Steve Rae   fastboot: sparse:...
43
  #include <fastboot.h>
e6ca1ad60   Steve Rae   implement the And...
44

40aeeda39   Maxime Ripard   sparse: Simplify ...
45
  #include <linux/math64.h>
0abd63b26   Steve Rae   fastboot: sparse:...
46
47
48
  #ifndef CONFIG_FASTBOOT_FLASH_FILLBUF_SIZE
  #define CONFIG_FASTBOOT_FLASH_FILLBUF_SIZE (1024 * 512)
  #endif
cc0f08cd3   Steve Rae   fastboot: sparse:...
49
50
  void write_sparse_image(
  		struct sparse_storage *info, const char *part_name,
9bc34799c   Steve Rae   fastboot: sparse:...
51
  		void *data, unsigned sz)
7bfc3b134   Maxime Ripard   sparse: Refactor ...
52
  {
cc0f08cd3   Steve Rae   fastboot: sparse:...
53
54
55
56
57
58
  	lbaint_t blk;
  	lbaint_t blkcnt;
  	lbaint_t blks;
  	uint32_t bytes_written = 0;
  	unsigned int chunk;
  	unsigned int offset;
080906706   Frank Li   MLK-19969 fastboo...
59
  	uint64_t chunk_data_sz;
cc0f08cd3   Steve Rae   fastboot: sparse:...
60
61
62
63
64
  	uint32_t *fill_buf = NULL;
  	uint32_t fill_val;
  	sparse_header_t *sparse_header;
  	chunk_header_t *chunk_header;
  	uint32_t total_blocks = 0;
0abd63b26   Steve Rae   fastboot: sparse:...
65
  	int fill_buf_num_blks;
cc0f08cd3   Steve Rae   fastboot: sparse:...
66
  	int i;
0abd63b26   Steve Rae   fastboot: sparse:...
67
68
69
  	int j;
  
  	fill_buf_num_blks = CONFIG_FASTBOOT_FLASH_FILLBUF_SIZE / info->blksz;
7bfc3b134   Maxime Ripard   sparse: Refactor ...
70

bb83c0f35   Maxime Ripard   sparse: Move main...
71
  	/* Read and skip over sparse image header */
cc0f08cd3   Steve Rae   fastboot: sparse:...
72
  	sparse_header = (sparse_header_t *)data;
bb83c0f35   Maxime Ripard   sparse: Move main...
73

cc0f08cd3   Steve Rae   fastboot: sparse:...
74
75
76
77
78
79
80
81
  	data += sparse_header->file_hdr_sz;
  	if (sparse_header->file_hdr_sz > sizeof(sparse_header_t)) {
  		/*
  		 * Skip the remaining bytes in a header that is longer than
  		 * we expected.
  		 */
  		data += (sparse_header->file_hdr_sz - sizeof(sparse_header_t));
  	}
bb83c0f35   Maxime Ripard   sparse: Move main...
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
  
  	debug("=== Sparse Image Header ===
  ");
  	debug("magic: 0x%x
  ", sparse_header->magic);
  	debug("major_version: 0x%x
  ", sparse_header->major_version);
  	debug("minor_version: 0x%x
  ", sparse_header->minor_version);
  	debug("file_hdr_sz: %d
  ", sparse_header->file_hdr_sz);
  	debug("chunk_hdr_sz: %d
  ", sparse_header->chunk_hdr_sz);
  	debug("blk_sz: %d
  ", sparse_header->blk_sz);
  	debug("total_blks: %d
  ", sparse_header->total_blks);
  	debug("total_chunks: %d
  ", sparse_header->total_chunks);
40aeeda39   Maxime Ripard   sparse: Simplify ...
101
102
103
104
  	/*
  	 * Verify that the sparse block size is a multiple of our
  	 * storage backend block size
  	 */
cc0f08cd3   Steve Rae   fastboot: sparse:...
105
  	div_u64_rem(sparse_header->blk_sz, info->blksz, &offset);
40aeeda39   Maxime Ripard   sparse: Simplify ...
106
  	if (offset) {
e6ca1ad60   Steve Rae   implement the And...
107
108
109
  		printf("%s: Sparse image block size issue [%u]
  ",
  		       __func__, sparse_header->blk_sz);
9bc34799c   Steve Rae   fastboot: sparse:...
110
  		fastboot_fail("sparse image block size issue");
cc0f08cd3   Steve Rae   fastboot: sparse:...
111
  		return;
e6ca1ad60   Steve Rae   implement the And...
112
  	}
64ece8485   Steve Rae   fastboot: sparse:...
113
114
  	puts("Flashing Sparse Image
  ");
e6ca1ad60   Steve Rae   implement the And...
115

b4e4bbe5a   Steve Rae   add code to handl...
116
  	/* Start processing chunks */
cc0f08cd3   Steve Rae   fastboot: sparse:...
117
  	blk = info->start;
7bfc3b134   Maxime Ripard   sparse: Refactor ...
118
  	for (chunk = 0; chunk < sparse_header->total_chunks; chunk++) {
cc0f08cd3   Steve Rae   fastboot: sparse:...
119
120
121
122
123
124
125
126
127
128
129
130
131
  		/* Read and skip over chunk header */
  		chunk_header = (chunk_header_t *)data;
  		data += sizeof(chunk_header_t);
  
  		if (chunk_header->chunk_type != CHUNK_TYPE_RAW) {
  			debug("=== Chunk Header ===
  ");
  			debug("chunk_type: 0x%x
  ", chunk_header->chunk_type);
  			debug("chunk_data_sz: 0x%x
  ", chunk_header->chunk_sz);
  			debug("total_size: 0x%x
  ", chunk_header->total_sz);
e6ca1ad60   Steve Rae   implement the And...
132
  		}
b4e4bbe5a   Steve Rae   add code to handl...
133

cc0f08cd3   Steve Rae   fastboot: sparse:...
134
135
136
137
138
139
140
  		if (sparse_header->chunk_hdr_sz > sizeof(chunk_header_t)) {
  			/*
  			 * Skip the remaining bytes in a header that is longer
  			 * than we expected.
  			 */
  			data += (sparse_header->chunk_hdr_sz -
  				 sizeof(chunk_header_t));
b4e4bbe5a   Steve Rae   add code to handl...
141
  		}
080906706   Frank Li   MLK-19969 fastboo...
142
  		chunk_data_sz = (uint64_t)sparse_header->blk_sz * (uint64_t)chunk_header->chunk_sz;
cc0f08cd3   Steve Rae   fastboot: sparse:...
143
144
145
146
147
  		blkcnt = chunk_data_sz / info->blksz;
  		switch (chunk_header->chunk_type) {
  		case CHUNK_TYPE_RAW:
  			if (chunk_header->total_sz !=
  			    (sparse_header->chunk_hdr_sz + chunk_data_sz)) {
9bc34799c   Steve Rae   fastboot: sparse:...
148
  				fastboot_fail(
cc0f08cd3   Steve Rae   fastboot: sparse:...
149
150
151
152
153
154
155
156
157
  					"Bogus chunk size for chunk type Raw");
  				return;
  			}
  
  			if (blk + blkcnt > info->start + info->size) {
  				printf(
  				    "%s: Request would exceed partition size!
  ",
  				    __func__);
9bc34799c   Steve Rae   fastboot: sparse:...
158
  				fastboot_fail(
cc0f08cd3   Steve Rae   fastboot: sparse:...
159
160
161
  				    "Request would exceed partition size!");
  				return;
  			}
e6ca1ad60   Steve Rae   implement the And...
162

cc0f08cd3   Steve Rae   fastboot: sparse:...
163
164
165
166
167
168
169
  			blks = info->write(info, blk, blkcnt, data);
  			/* blks might be > blkcnt (eg. NAND bad-blocks) */
  			if (blks < blkcnt) {
  				printf("%s: %s" LBAFU " [" LBAFU "]
  ",
  				       __func__, "Write failed, block #",
  				       blk, blks);
9bc34799c   Steve Rae   fastboot: sparse:...
170
  				fastboot_fail(
cc0f08cd3   Steve Rae   fastboot: sparse:...
171
172
173
174
175
176
177
178
179
180
181
182
  					      "flash write failure");
  				return;
  			}
  			blk += blks;
  			bytes_written += blkcnt * info->blksz;
  			total_blocks += chunk_header->chunk_sz;
  			data += chunk_data_sz;
  			break;
  
  		case CHUNK_TYPE_FILL:
  			if (chunk_header->total_sz !=
  			    (sparse_header->chunk_hdr_sz + sizeof(uint32_t))) {
9bc34799c   Steve Rae   fastboot: sparse:...
183
  				fastboot_fail(
cc0f08cd3   Steve Rae   fastboot: sparse:...
184
185
186
  					"Bogus chunk size for chunk type FILL");
  				return;
  			}
b4e4bbe5a   Steve Rae   add code to handl...
187

cc0f08cd3   Steve Rae   fastboot: sparse:...
188
189
  			fill_buf = (uint32_t *)
  				   memalign(ARCH_DMA_MINALIGN,
0abd63b26   Steve Rae   fastboot: sparse:...
190
191
192
  					    ROUNDUP(
  						info->blksz * fill_buf_num_blks,
  						ARCH_DMA_MINALIGN));
cc0f08cd3   Steve Rae   fastboot: sparse:...
193
  			if (!fill_buf) {
9bc34799c   Steve Rae   fastboot: sparse:...
194
  				fastboot_fail(
cc0f08cd3   Steve Rae   fastboot: sparse:...
195
196
197
  					"Malloc failed for: CHUNK_TYPE_FILL");
  				return;
  			}
b4e4bbe5a   Steve Rae   add code to handl...
198

cc0f08cd3   Steve Rae   fastboot: sparse:...
199
200
  			fill_val = *(uint32_t *)data;
  			data = (char *)data + sizeof(uint32_t);
a5d1e04a5   Maxime Ripard   sparse: Implement...
201

0abd63b26   Steve Rae   fastboot: sparse:...
202
203
204
205
  			for (i = 0;
  			     i < (info->blksz * fill_buf_num_blks /
  				  sizeof(fill_val));
  			     i++)
cc0f08cd3   Steve Rae   fastboot: sparse:...
206
  				fill_buf[i] = fill_val;
a5d1e04a5   Maxime Ripard   sparse: Implement...
207

cc0f08cd3   Steve Rae   fastboot: sparse:...
208
209
210
211
212
  			if (blk + blkcnt > info->start + info->size) {
  				printf(
  				    "%s: Request would exceed partition size!
  ",
  				    __func__);
9bc34799c   Steve Rae   fastboot: sparse:...
213
  				fastboot_fail(
cc0f08cd3   Steve Rae   fastboot: sparse:...
214
  				    "Request would exceed partition size!");
bc23ae569   Ye Li   MLK-20356-1 commo...
215
  				free(fill_buf);
cc0f08cd3   Steve Rae   fastboot: sparse:...
216
  				return;
b4e4bbe5a   Steve Rae   add code to handl...
217
  			}
b4e4bbe5a   Steve Rae   add code to handl...
218

0abd63b26   Steve Rae   fastboot: sparse:...
219
220
221
222
223
224
225
226
227
228
229
230
  			for (i = 0; i < blkcnt;) {
  				j = blkcnt - i;
  				if (j > fill_buf_num_blks)
  					j = fill_buf_num_blks;
  				blks = info->write(info, blk, j, fill_buf);
  				/* blks might be > j (eg. NAND bad-blocks) */
  				if (blks < j) {
  					printf("%s: %s " LBAFU " [%d]
  ",
  					       __func__,
  					       "Write failed, block #",
  					       blk, j);
9bc34799c   Steve Rae   fastboot: sparse:...
231
  					fastboot_fail(
cc0f08cd3   Steve Rae   fastboot: sparse:...
232
233
234
235
236
  						      "flash write failure");
  					free(fill_buf);
  					return;
  				}
  				blk += blks;
0abd63b26   Steve Rae   fastboot: sparse:...
237
  				i += j;
cc0f08cd3   Steve Rae   fastboot: sparse:...
238
239
240
241
242
  			}
  			bytes_written += blkcnt * info->blksz;
  			total_blocks += chunk_data_sz / sparse_header->blk_sz;
  			free(fill_buf);
  			break;
7bfc3b134   Maxime Ripard   sparse: Refactor ...
243

cc0f08cd3   Steve Rae   fastboot: sparse:...
244
  		case CHUNK_TYPE_DONT_CARE:
2c7240468   Steve Rae   fastboot: sparse:...
245
  			blk += info->reserve(info, blk, blkcnt);
cc0f08cd3   Steve Rae   fastboot: sparse:...
246
  			total_blocks += chunk_header->chunk_sz;
cc0f08cd3   Steve Rae   fastboot: sparse:...
247
248
249
250
251
  			break;
  
  		case CHUNK_TYPE_CRC32:
  			if (chunk_header->total_sz !=
  			    sparse_header->chunk_hdr_sz) {
9bc34799c   Steve Rae   fastboot: sparse:...
252
  				fastboot_fail(
cc0f08cd3   Steve Rae   fastboot: sparse:...
253
254
255
256
257
258
259
260
261
262
263
  					"Bogus chunk size for chunk type Dont Care");
  				return;
  			}
  			total_blocks += chunk_header->chunk_sz;
  			data += chunk_data_sz;
  			break;
  
  		default:
  			printf("%s: Unknown chunk type: %x
  ", __func__,
  			       chunk_header->chunk_type);
9bc34799c   Steve Rae   fastboot: sparse:...
264
  			fastboot_fail("Unknown chunk type");
cc0f08cd3   Steve Rae   fastboot: sparse:...
265
266
  			return;
  		}
b4e4bbe5a   Steve Rae   add code to handl...
267
  	}
e3793541b   Steve Rae   fastboot: sparse:...
268
269
  	debug("Wrote %d blocks, expected to write %d blocks
  ",
cc0f08cd3   Steve Rae   fastboot: sparse:...
270
271
272
  	      total_blocks, sparse_header->total_blks);
  	printf("........ wrote %u bytes to '%s'
  ", bytes_written, part_name);
a5d1e04a5   Maxime Ripard   sparse: Implement...
273

cc0f08cd3   Steve Rae   fastboot: sparse:...
274
  	if (total_blocks != sparse_header->total_blks)
9bc34799c   Steve Rae   fastboot: sparse:...
275
  		fastboot_fail("sparse image write failure");
cc0f08cd3   Steve Rae   fastboot: sparse:...
276
  	else
9bc34799c   Steve Rae   fastboot: sparse:...
277
  		fastboot_okay("");
b4e4bbe5a   Steve Rae   add code to handl...
278

cc0f08cd3   Steve Rae   fastboot: sparse:...
279
  	return;
b4e4bbe5a   Steve Rae   add code to handl...
280
  }