1 /* 2 * Copyright (C) 2008 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include "bootloader.h" 18 #include "common.h" 19 #include "mtdutils/mtdutils.h" 20 #include "roots.h" 21 22 #include <errno.h> 23 #include <stdio.h> 24 #include <string.h> 25 26 static const int MISC_PAGES = 3; // number of pages to save 27 static const int MISC_COMMAND_PAGE = 1; // bootloader command is this page 28 29 #undef LOGE 30 #define LOGE(...) fprintf(stderr, "E:" __VA_ARGS__) 31 32 #ifdef LOG_VERBOSE 33 static void dump_data(const char *data, int len) { 34 int pos; 35 for (pos = 0; pos < len; ) { 36 printf("%05x: %02x", pos, data[pos]); 37 for (++pos; pos < len && (pos % 24) != 0; ++pos) { 38 printf(" %02x", data[pos]); 39 } 40 printf("\n"); 41 } 42 } 43 #endif 44 45 int get_bootloader_message(struct bootloader_message *out) { 46 size_t write_size; 47 const MtdPartition *part = mtd_find_partition_by_name(MISC_NAME); 48 if (part == NULL || mtd_partition_info(part, NULL, NULL, &write_size)) { 49 LOGE("Can't find %s\n", MISC_NAME); 50 return -1; 51 } 52 53 MtdReadContext *read = mtd_read_partition(part); 54 if (read == NULL) { 55 LOGE("Can't open %s\n(%s)\n", MISC_NAME, strerror(errno)); 56 return -1; 57 } 58 59 const ssize_t size = write_size * MISC_PAGES; 60 char data[size]; 61 ssize_t r = mtd_read_data(read, data, size); 62 if (r != size) LOGE("Can't read %s\n(%s)\n", MISC_NAME, strerror(errno)); 63 mtd_read_close(read); 64 if (r != size) return -1; 65 66 #ifdef LOG_VERBOSE 67 printf("\n--- get_bootloader_message ---\n"); 68 dump_data(data, size); 69 printf("\n"); 70 #endif 71 72 memcpy(out, &data[write_size * MISC_COMMAND_PAGE], sizeof(*out)); 73 return 0; 74 } 75 76 int set_bootloader_message(const struct bootloader_message *in) { 77 size_t write_size; 78 const MtdPartition *part = mtd_find_partition_by_name(MISC_NAME); 79 if (part == NULL || mtd_partition_info(part, NULL, NULL, &write_size)) { 80 LOGE("Can't find %s\n", MISC_NAME); 81 return -1; 82 } 83 84 MtdReadContext *read = mtd_read_partition(part); 85 if (read == NULL) { 86 LOGE("Can't open %s\n(%s)\n", MISC_NAME, strerror(errno)); 87 return -1; 88 } 89 90 ssize_t size = write_size * MISC_PAGES; 91 char data[size]; 92 ssize_t r = mtd_read_data(read, data, size); 93 if (r != size) LOGE("Can't read %s\n(%s)\n", MISC_NAME, strerror(errno)); 94 mtd_read_close(read); 95 if (r != size) return -1; 96 97 memcpy(&data[write_size * MISC_COMMAND_PAGE], in, sizeof(*in)); 98 99 #ifdef LOG_VERBOSE 100 printf("\n--- set_bootloader_message ---\n"); 101 dump_data(data, size); 102 printf("\n"); 103 #endif 104 105 MtdWriteContext *write = mtd_write_partition(part); 106 if (write == NULL) { 107 LOGE("Can't open %s\n(%s)\n", MISC_NAME, strerror(errno)); 108 return -1; 109 } 110 if (mtd_write_data(write, data, size) != size) { 111 LOGE("Can't write %s\n(%s)\n", MISC_NAME, strerror(errno)); 112 mtd_write_close(write); 113 return -1; 114 } 115 if (mtd_write_close(write)) { 116 LOGE("Can't finish %s\n(%s)\n", MISC_NAME, strerror(errno)); 117 return -1; 118 } 119 120 LOGI("Set boot command \"%s\"\n", in->command[0] != 255 ? in->command : ""); 121 return 0; 122 } 123 124 /* Update Image 125 * 126 * - will be stored in the "cache" partition 127 * - bad blocks will be ignored, like boot.img and recovery.img 128 * - the first block will be the image header (described below) 129 * - the size is in BYTES, inclusive of the header 130 * - offsets are in BYTES from the start of the update header 131 * - two raw bitmaps will be included, the "busy" and "fail" bitmaps 132 * - for dream, the bitmaps will be 320x480x16bpp RGB565 133 */ 134 135 struct update_header { 136 unsigned char MAGIC[UPDATE_MAGIC_SIZE]; 137 138 unsigned version; 139 unsigned size; 140 141 unsigned image_offset; 142 unsigned image_length; 143 144 unsigned bitmap_width; 145 unsigned bitmap_height; 146 unsigned bitmap_bpp; 147 148 unsigned busy_bitmap_offset; 149 unsigned busy_bitmap_length; 150 151 unsigned fail_bitmap_offset; 152 unsigned fail_bitmap_length; 153 }; 154 155 int write_update_for_bootloader( 156 const char *update, int update_length, 157 int bitmap_width, int bitmap_height, int bitmap_bpp, 158 const char *busy_bitmap, const char *fail_bitmap, 159 const char *log_filename) { 160 const MtdPartition *part = mtd_find_partition_by_name(CACHE_NAME); 161 if (part == NULL) { 162 LOGE("Can't find %s\n", CACHE_NAME); 163 return -1; 164 } 165 166 MtdWriteContext *write = mtd_write_partition(part); 167 if (write == NULL) { 168 LOGE("Can't open %s\n(%s)\n", CACHE_NAME, strerror(errno)); 169 return -1; 170 } 171 172 /* Write an invalid (zero) header first, to disable any previous 173 * update and any other structured contents (like a filesystem), 174 * and as a placeholder for the amount of space required. 175 */ 176 177 struct update_header header; 178 memset(&header, 0, sizeof(header)); 179 const ssize_t header_size = sizeof(header); 180 if (mtd_write_data(write, (char*) &header, header_size) != header_size) { 181 LOGE("Can't write header to %s\n(%s)\n", CACHE_NAME, strerror(errno)); 182 mtd_write_close(write); 183 return -1; 184 } 185 186 /* Write each section individually block-aligned, so we can write 187 * each block independently without complicated buffering. 188 */ 189 190 memcpy(&header.MAGIC, UPDATE_MAGIC, UPDATE_MAGIC_SIZE); 191 header.version = UPDATE_VERSION; 192 header.size = header_size; 193 194 if (log_filename != NULL) { 195 // Write 1 byte into the following block, then fill to the end 196 // in order to reserve that block. We'll use the block to 197 // send a copy of the log through to the next invocation of 198 // recovery. We write the log as late as possible in order to 199 // capture any messages emitted by this function. 200 mtd_erase_blocks(write, 0); 201 if (mtd_write_data(write, (char*) &header, 1) != 1) { 202 LOGE("Can't write log block to %s\n(%s)\n", 203 CACHE_NAME, strerror(errno)); 204 mtd_write_close(write); 205 return -1; 206 } 207 } 208 209 off_t image_start_pos = mtd_erase_blocks(write, 0); 210 header.image_length = update_length; 211 if ((int) header.image_offset == -1 || 212 mtd_write_data(write, update, update_length) != update_length) { 213 LOGE("Can't write update to %s\n(%s)\n", CACHE_NAME, strerror(errno)); 214 mtd_write_close(write); 215 return -1; 216 } 217 off_t busy_start_pos = mtd_erase_blocks(write, 0); 218 header.image_offset = mtd_find_write_start(write, image_start_pos); 219 220 header.bitmap_width = bitmap_width; 221 header.bitmap_height = bitmap_height; 222 header.bitmap_bpp = bitmap_bpp; 223 224 int bitmap_length = (bitmap_bpp + 7) / 8 * bitmap_width * bitmap_height; 225 226 LOGE("writing busy bitmap\n"); 227 header.busy_bitmap_length = busy_bitmap != NULL ? bitmap_length : 0; 228 if ((int) header.busy_bitmap_offset == -1 || 229 mtd_write_data(write, busy_bitmap, bitmap_length) != bitmap_length) { 230 LOGE("Can't write bitmap to %s\n(%s)\n", CACHE_NAME, strerror(errno)); 231 mtd_write_close(write); 232 return -1; 233 } 234 LOGE("busy bitmap written\n"); 235 off_t fail_start_pos = mtd_erase_blocks(write, 0); 236 LOGE("block padded\n"); 237 header.busy_bitmap_offset = mtd_find_write_start(write, busy_start_pos); 238 239 header.fail_bitmap_length = fail_bitmap != NULL ? bitmap_length : 0; 240 if ((int) header.fail_bitmap_offset == -1 || 241 mtd_write_data(write, fail_bitmap, bitmap_length) != bitmap_length) { 242 LOGE("Can't write bitmap to %s\n(%s)\n", CACHE_NAME, strerror(errno)); 243 mtd_write_close(write); 244 return -1; 245 } 246 LOGE("finishing block\n"); 247 mtd_erase_blocks(write, 0); 248 LOGE("finished block\n"); 249 header.fail_bitmap_offset = mtd_find_write_start(write, fail_start_pos); 250 251 /* Write the header last, after all the blocks it refers to, so that 252 * when the magic number is installed everything is valid. 253 */ 254 255 if (mtd_write_close(write)) { 256 LOGE("Can't finish writing %s\n(%s)\n", CACHE_NAME, strerror(errno)); 257 return -1; 258 } 259 260 write = mtd_write_partition(part); 261 if (write == NULL) { 262 LOGE("Can't reopen %s\n(%s)\n", CACHE_NAME, strerror(errno)); 263 return -1; 264 } 265 266 if (mtd_write_data(write, (char*) &header, header_size) != header_size) { 267 LOGE("Can't rewrite header to %s\n(%s)\n", CACHE_NAME, strerror(errno)); 268 mtd_write_close(write); 269 return -1; 270 } 271 272 if (log_filename != NULL) { 273 LOGE("writing log\n"); 274 size_t erase_size; 275 if (mtd_partition_info(part, NULL, &erase_size, NULL) != 0) { 276 LOGE("Error reading block size\n(%s)\n", strerror(errno)); 277 mtd_write_close(write); 278 return -1; 279 } 280 mtd_erase_blocks(write, 0); 281 282 if (erase_size > 0) { 283 char* log = malloc(erase_size); 284 FILE* f = fopen(log_filename, "rb"); 285 // The fseek() may fail if it tries to go before the 286 // beginning of the log, but that's okay because we want 287 // to be positioned at the start anyway. 288 fseek(f, -(erase_size-sizeof(size_t)-LOG_MAGIC_SIZE), SEEK_END); 289 memcpy(log, LOG_MAGIC, LOG_MAGIC_SIZE); 290 size_t read = fread(log+sizeof(size_t)+LOG_MAGIC_SIZE, 291 1, erase_size-sizeof(size_t)-LOG_MAGIC_SIZE, f); 292 LOGI("read %d bytes from log\n", (int)read); 293 *(size_t *)(log + LOG_MAGIC_SIZE) = read; 294 fclose(f); 295 if (mtd_write_data(write, log, erase_size) != erase_size) { 296 LOGE("failed to store log in cache partition\n(%s)\n", 297 strerror(errno)); 298 mtd_write_close(write); 299 } 300 free(log); 301 } 302 } 303 304 if (mtd_erase_blocks(write, 0) != image_start_pos) { 305 LOGE("Misalignment rewriting %s\n(%s)\n", CACHE_NAME, strerror(errno)); 306 mtd_write_close(write); 307 return -1; 308 } 309 310 LOGE("closing partition\n"); 311 if (mtd_write_close(write)) { 312 LOGE("Can't finish header of %s\n(%s)\n", CACHE_NAME, strerror(errno)); 313 return -1; 314 } 315 316 return 0; 317 } 318