Blame view

lib/image-sparse.c 7.92 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>
40aeeda39   Maxime Ripard   sparse: Simplify ...
43
  #include <linux/math64.h>
c4ded03ef   Alex Kiernan   fastboot: Refacto...
44
  static void default_log(const char *ignored, char *response) {}
2f83f219b   Jassi Brar   fastboot: sparse:...
45
46
  
  int write_sparse_image(struct sparse_storage *info,
c4ded03ef   Alex Kiernan   fastboot: Refacto...
47
  		       const char *part_name, void *data, char *response)
7bfc3b134   Maxime Ripard   sparse: Refactor ...
48
  {
cc0f08cd3   Steve Rae   fastboot: sparse:...
49
50
51
52
53
54
  	lbaint_t blk;
  	lbaint_t blkcnt;
  	lbaint_t blks;
  	uint32_t bytes_written = 0;
  	unsigned int chunk;
  	unsigned int offset;
af09befee   Frank Li   MLK-19969 fastboo...
55
  	uint64_t chunk_data_sz;
cc0f08cd3   Steve Rae   fastboot: sparse:...
56
57
58
59
60
  	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:...
61
  	int fill_buf_num_blks;
cc0f08cd3   Steve Rae   fastboot: sparse:...
62
  	int i;
0abd63b26   Steve Rae   fastboot: sparse:...
63
  	int j;
c232d14d1   Alex Kiernan   mmc: Separate "mm...
64
  	fill_buf_num_blks = CONFIG_IMAGE_SPARSE_FILLBUF_SIZE / info->blksz;
7bfc3b134   Maxime Ripard   sparse: Refactor ...
65

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

cc0f08cd3   Steve Rae   fastboot: sparse:...
69
70
71
72
73
74
75
76
  	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...
77

2f83f219b   Jassi Brar   fastboot: sparse:...
78
79
  	if (!info->mssg)
  		info->mssg = default_log;
bb83c0f35   Maxime Ripard   sparse: Move main...
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
  	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 ...
98
99
100
101
  	/*
  	 * Verify that the sparse block size is a multiple of our
  	 * storage backend block size
  	 */
cc0f08cd3   Steve Rae   fastboot: sparse:...
102
  	div_u64_rem(sparse_header->blk_sz, info->blksz, &offset);
40aeeda39   Maxime Ripard   sparse: Simplify ...
103
  	if (offset) {
e6ca1ad60   Steve Rae   implement the And...
104
105
106
  		printf("%s: Sparse image block size issue [%u]
  ",
  		       __func__, sparse_header->blk_sz);
c4ded03ef   Alex Kiernan   fastboot: Refacto...
107
  		info->mssg("sparse image block size issue", response);
2f83f219b   Jassi Brar   fastboot: sparse:...
108
  		return -1;
e6ca1ad60   Steve Rae   implement the And...
109
  	}
64ece8485   Steve Rae   fastboot: sparse:...
110
111
  	puts("Flashing Sparse Image
  ");
e6ca1ad60   Steve Rae   implement the And...
112

b4e4bbe5a   Steve Rae   add code to handl...
113
  	/* Start processing chunks */
cc0f08cd3   Steve Rae   fastboot: sparse:...
114
  	blk = info->start;
7bfc3b134   Maxime Ripard   sparse: Refactor ...
115
  	for (chunk = 0; chunk < sparse_header->total_chunks; chunk++) {
cc0f08cd3   Steve Rae   fastboot: sparse:...
116
117
118
119
120
121
122
123
124
125
126
127
128
  		/* 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...
129
  		}
b4e4bbe5a   Steve Rae   add code to handl...
130

cc0f08cd3   Steve Rae   fastboot: sparse:...
131
132
133
134
135
136
137
  		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...
138
  		}
af09befee   Frank Li   MLK-19969 fastboo...
139
  		chunk_data_sz = (uint64_t)sparse_header->blk_sz * (uint64_t)chunk_header->chunk_sz;
cc0f08cd3   Steve Rae   fastboot: sparse:...
140
141
142
143
144
  		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)) {
c4ded03ef   Alex Kiernan   fastboot: Refacto...
145
146
  				info->mssg("Bogus chunk size for chunk type Raw",
  					   response);
2f83f219b   Jassi Brar   fastboot: sparse:...
147
  				return -1;
cc0f08cd3   Steve Rae   fastboot: sparse:...
148
149
150
151
152
153
154
  			}
  
  			if (blk + blkcnt > info->start + info->size) {
  				printf(
  				    "%s: Request would exceed partition size!
  ",
  				    __func__);
c4ded03ef   Alex Kiernan   fastboot: Refacto...
155
156
  				info->mssg("Request would exceed partition size!",
  					   response);
2f83f219b   Jassi Brar   fastboot: sparse:...
157
  				return -1;
cc0f08cd3   Steve Rae   fastboot: sparse:...
158
  			}
e6ca1ad60   Steve Rae   implement the And...
159

cc0f08cd3   Steve Rae   fastboot: sparse:...
160
161
162
163
164
165
166
  			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);
c4ded03ef   Alex Kiernan   fastboot: Refacto...
167
  				info->mssg("flash write failure", response);
2f83f219b   Jassi Brar   fastboot: sparse:...
168
  				return -1;
cc0f08cd3   Steve Rae   fastboot: sparse:...
169
170
171
172
173
174
175
176
177
178
  			}
  			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))) {
c4ded03ef   Alex Kiernan   fastboot: Refacto...
179
  				info->mssg("Bogus chunk size for chunk type FILL", response);
2f83f219b   Jassi Brar   fastboot: sparse:...
180
  				return -1;
cc0f08cd3   Steve Rae   fastboot: sparse:...
181
  			}
b4e4bbe5a   Steve Rae   add code to handl...
182

cc0f08cd3   Steve Rae   fastboot: sparse:...
183
184
  			fill_buf = (uint32_t *)
  				   memalign(ARCH_DMA_MINALIGN,
0abd63b26   Steve Rae   fastboot: sparse:...
185
186
187
  					    ROUNDUP(
  						info->blksz * fill_buf_num_blks,
  						ARCH_DMA_MINALIGN));
cc0f08cd3   Steve Rae   fastboot: sparse:...
188
  			if (!fill_buf) {
c4ded03ef   Alex Kiernan   fastboot: Refacto...
189
190
  				info->mssg("Malloc failed for: CHUNK_TYPE_FILL",
  					   response);
2f83f219b   Jassi Brar   fastboot: sparse:...
191
  				return -1;
cc0f08cd3   Steve Rae   fastboot: sparse:...
192
  			}
b4e4bbe5a   Steve Rae   add code to handl...
193

cc0f08cd3   Steve Rae   fastboot: sparse:...
194
195
  			fill_val = *(uint32_t *)data;
  			data = (char *)data + sizeof(uint32_t);
a5d1e04a5   Maxime Ripard   sparse: Implement...
196

0abd63b26   Steve Rae   fastboot: sparse:...
197
198
199
200
  			for (i = 0;
  			     i < (info->blksz * fill_buf_num_blks /
  				  sizeof(fill_val));
  			     i++)
cc0f08cd3   Steve Rae   fastboot: sparse:...
201
  				fill_buf[i] = fill_val;
a5d1e04a5   Maxime Ripard   sparse: Implement...
202

cc0f08cd3   Steve Rae   fastboot: sparse:...
203
204
205
206
207
  			if (blk + blkcnt > info->start + info->size) {
  				printf(
  				    "%s: Request would exceed partition size!
  ",
  				    __func__);
c4ded03ef   Alex Kiernan   fastboot: Refacto...
208
209
  				info->mssg("Request would exceed partition size!",
  					   response);
0a496da08   Ye Li   MLK-20356-1 commo...
210
  				free(fill_buf);
2f83f219b   Jassi Brar   fastboot: sparse:...
211
  				return -1;
b4e4bbe5a   Steve Rae   add code to handl...
212
  			}
b4e4bbe5a   Steve Rae   add code to handl...
213

0abd63b26   Steve Rae   fastboot: sparse:...
214
215
216
217
218
219
220
221
222
223
224
225
  			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);
c4ded03ef   Alex Kiernan   fastboot: Refacto...
226
227
  					info->mssg("flash write failure",
  						   response);
cc0f08cd3   Steve Rae   fastboot: sparse:...
228
  					free(fill_buf);
2f83f219b   Jassi Brar   fastboot: sparse:...
229
  					return -1;
cc0f08cd3   Steve Rae   fastboot: sparse:...
230
231
  				}
  				blk += blks;
0abd63b26   Steve Rae   fastboot: sparse:...
232
  				i += j;
cc0f08cd3   Steve Rae   fastboot: sparse:...
233
234
235
236
237
  			}
  			bytes_written += blkcnt * info->blksz;
  			total_blocks += chunk_data_sz / sparse_header->blk_sz;
  			free(fill_buf);
  			break;
7bfc3b134   Maxime Ripard   sparse: Refactor ...
238

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

2f83f219b   Jassi Brar   fastboot: sparse:...
269
  	if (total_blocks != sparse_header->total_blks) {
c4ded03ef   Alex Kiernan   fastboot: Refacto...
270
  		info->mssg("sparse image write failure", response);
2f83f219b   Jassi Brar   fastboot: sparse:...
271
272
  		return -1;
  	}
b4e4bbe5a   Steve Rae   add code to handl...
273

2f83f219b   Jassi Brar   fastboot: sparse:...
274
  	return 0;
b4e4bbe5a   Steve Rae   add code to handl...
275
  }