@@ -119,3 +119,153 @@ int set_bootloader_message(const struct bootloader_message *in) {
119
119
LOGI ("Set boot command \"%s\"\n" , in -> command [0 ] != 255 ? in -> command : "" );
120
120
return 0 ;
121
121
}
122
+
123
+ /* Update Image
124
+ *
125
+ * - will be stored in the "cache" partition
126
+ * - bad blocks will be ignored, like boot.img and recovery.img
127
+ * - the first block will be the image header (described below)
128
+ * - the size is in BYTES, inclusive of the header
129
+ * - offsets are in BYTES from the start of the update header
130
+ * - two raw bitmaps will be included, the "busy" and "fail" bitmaps
131
+ * - for dream, the bitmaps will be 320x480x16bpp RGB565
132
+ */
133
+
134
+ #define UPDATE_MAGIC "MSM-RADIO-UPDATE"
135
+ #define UPDATE_MAGIC_SIZE 16
136
+ #define UPDATE_VERSION 0x00010000
137
+
138
+ struct update_header {
139
+ unsigned char MAGIC [UPDATE_MAGIC_SIZE ];
140
+
141
+ unsigned version ;
142
+ unsigned size ;
143
+
144
+ unsigned image_offset ;
145
+ unsigned image_length ;
146
+
147
+ unsigned bitmap_width ;
148
+ unsigned bitmap_height ;
149
+ unsigned bitmap_bpp ;
150
+
151
+ unsigned busy_bitmap_offset ;
152
+ unsigned busy_bitmap_length ;
153
+
154
+ unsigned fail_bitmap_offset ;
155
+ unsigned fail_bitmap_length ;
156
+ };
157
+
158
+ int write_update_for_bootloader (
159
+ const char * update , int update_length ,
160
+ int bitmap_width , int bitmap_height , int bitmap_bpp ,
161
+ const char * busy_bitmap , const char * fail_bitmap ) {
162
+ if (ensure_root_path_unmounted (CACHE_NAME )) {
163
+ LOGE ("Can't unmount %s\n" , CACHE_NAME );
164
+ return -1 ;
165
+ }
166
+
167
+ const MtdPartition * part = get_root_mtd_partition (CACHE_NAME );
168
+ if (part == NULL ) {
169
+ LOGE ("Can't find %s\n" , CACHE_NAME );
170
+ return -1 ;
171
+ }
172
+
173
+ MtdWriteContext * write = mtd_write_partition (part );
174
+ if (write == NULL ) {
175
+ LOGE ("Can't open %s\n(%s)\n" , CACHE_NAME , strerror (errno ));
176
+ return -1 ;
177
+ }
178
+
179
+ /* Write an invalid (zero) header first, to disable any previous
180
+ * update and any other structured contents (like a filesystem),
181
+ * and as a placeholder for the amount of space required.
182
+ */
183
+
184
+ struct update_header header ;
185
+ memset (& header , 0 , sizeof (header ));
186
+ const ssize_t header_size = sizeof (header );
187
+ if (mtd_write_data (write , (char * ) & header , header_size ) != header_size ) {
188
+ LOGE ("Can't write header to %s\n(%s)\n" , CACHE_NAME , strerror (errno ));
189
+ mtd_write_close (write );
190
+ return -1 ;
191
+ }
192
+
193
+ /* Write each section individually block-aligned, so we can write
194
+ * each block independently without complicated buffering.
195
+ */
196
+
197
+ memcpy (& header .MAGIC , UPDATE_MAGIC , UPDATE_MAGIC_SIZE );
198
+ header .version = UPDATE_VERSION ;
199
+ header .size = header_size ;
200
+
201
+ off_t image_start_pos = mtd_erase_blocks (write , 0 );
202
+ header .image_length = update_length ;
203
+ if ((int ) header .image_offset == -1 ||
204
+ mtd_write_data (write , update , update_length ) != update_length ) {
205
+ LOGE ("Can't write update to %s\n(%s)\n" , CACHE_NAME , strerror (errno ));
206
+ mtd_write_close (write );
207
+ return -1 ;
208
+ }
209
+ off_t busy_start_pos = mtd_erase_blocks (write , 0 );
210
+ header .image_offset = mtd_find_write_start (write , image_start_pos );
211
+
212
+ header .bitmap_width = bitmap_width ;
213
+ header .bitmap_height = bitmap_height ;
214
+ header .bitmap_bpp = bitmap_bpp ;
215
+
216
+ int bitmap_length = (bitmap_bpp + 7 ) / 8 * bitmap_width * bitmap_height ;
217
+
218
+ header .busy_bitmap_length = busy_bitmap != NULL ? bitmap_length : 0 ;
219
+ if ((int ) header .busy_bitmap_offset == -1 ||
220
+ mtd_write_data (write , busy_bitmap , bitmap_length ) != bitmap_length ) {
221
+ LOGE ("Can't write bitmap to %s\n(%s)\n" , CACHE_NAME , strerror (errno ));
222
+ mtd_write_close (write );
223
+ return -1 ;
224
+ }
225
+ off_t fail_start_pos = mtd_erase_blocks (write , 0 );
226
+ header .busy_bitmap_offset = mtd_find_write_start (write , busy_start_pos );
227
+
228
+ header .fail_bitmap_length = fail_bitmap != NULL ? bitmap_length : 0 ;
229
+ if ((int ) header .fail_bitmap_offset == -1 ||
230
+ mtd_write_data (write , fail_bitmap , bitmap_length ) != bitmap_length ) {
231
+ LOGE ("Can't write bitmap to %s\n(%s)\n" , CACHE_NAME , strerror (errno ));
232
+ mtd_write_close (write );
233
+ return -1 ;
234
+ }
235
+ mtd_erase_blocks (write , 0 );
236
+ header .fail_bitmap_offset = mtd_find_write_start (write , fail_start_pos );
237
+
238
+ /* Write the header last, after all the blocks it refers to, so that
239
+ * when the magic number is installed everything is valid.
240
+ */
241
+
242
+ if (mtd_write_close (write )) {
243
+ LOGE ("Can't finish writing %s\n(%s)\n" , CACHE_NAME , strerror (errno ));
244
+ return -1 ;
245
+ }
246
+
247
+ write = mtd_write_partition (part );
248
+ if (write == NULL ) {
249
+ LOGE ("Can't reopen %s\n(%s)\n" , CACHE_NAME , strerror (errno ));
250
+ return -1 ;
251
+ }
252
+
253
+ if (mtd_write_data (write , (char * ) & header , header_size ) != header_size ) {
254
+ LOGE ("Can't rewrite header to %s\n(%s)\n" , CACHE_NAME , strerror (errno ));
255
+ mtd_write_close (write );
256
+ return -1 ;
257
+ }
258
+
259
+ if (mtd_erase_blocks (write , 0 ) != image_start_pos ) {
260
+ LOGE ("Misalignment rewriting %s\n(%s)\n" , CACHE_NAME , strerror (errno ));
261
+ mtd_write_close (write );
262
+ return -1 ;
263
+ }
264
+
265
+ if (mtd_write_close (write )) {
266
+ LOGE ("Can't finish header of %s\n(%s)\n" , CACHE_NAME , strerror (errno ));
267
+ return -1 ;
268
+ }
269
+
270
+ return 0 ;
271
+ }
0 commit comments