int get_bootloader_message(struct bootloader_message *out) { size_t write_size; const MtdPartition *part = get_root_mtd_partition(MISC_NAME); if (part == NULL || mtd_partition_info(part, NULL, NULL, &write_size)) { LOGE("Can't find %s\n", MISC_NAME); return -1; } MtdReadContext *read = mtd_read_partition(part); if (read == NULL) { LOGE("Can't open %s\n(%s)\n", MISC_NAME, strerror(errno)); return -1; } const ssize_t size = write_size * MISC_PAGES; char data[size]; ssize_t r = mtd_read_data(read, data, size); if (r != size) LOGE("Can't read %s\n(%s)\n", MISC_NAME, strerror(errno)); mtd_read_close(read); if (r != size) return -1; #ifdef LOG_VERBOSE printf("\n--- get_bootloader_message ---\n"); dump_data(data, size); printf("\n"); #endif memcpy(out, &data[write_size * MISC_COMMAND_PAGE], sizeof(*out)); return 0; }
int set_bootloader_message(const struct bootloader_message *in) { size_t write_size; const MtdPartition *part = get_root_mtd_partition(MISC_NAME); if (part == NULL || mtd_partition_info(part, NULL, NULL, &write_size)) { LOGE("Can't find %s\n", MISC_NAME); return -1; } MtdReadContext *read = mtd_read_partition(part); if (read == NULL) { LOGE("Can't open %s\n(%s)\n", MISC_NAME, strerror(errno)); return -1; } ssize_t size = write_size * MISC_PAGES; char data[size]; ssize_t r = mtd_read_data(read, data, size); if (r != size) LOGE("Can't read %s\n(%s)\n", MISC_NAME, strerror(errno)); mtd_read_close(read); if (r != size) return -1; memcpy(&data[write_size * MISC_COMMAND_PAGE], in, sizeof(*in)); #ifdef LOG_VERBOSE printf("\n--- set_bootloader_message ---\n"); dump_data(data, size); printf("\n"); #endif MtdWriteContext *write = mtd_write_partition(part); if (write == NULL) { LOGE("Can't open %s\n(%s)\n", MISC_NAME, strerror(errno)); return -1; } if (mtd_write_data(write, data, size) != size) { LOGE("Can't write %s\n(%s)\n", MISC_NAME, strerror(errno)); mtd_write_close(write); return -1; } if (mtd_write_close(write)) { LOGE("Can't finish %s\n(%s)\n", MISC_NAME, strerror(errno)); return -1; } LOGI("Set boot command \"%s\"\n", in->command[0] != 255 ? in->command : ""); return 0; }
void write_fstab_root(char *root_path, FILE *file) { RootInfo *info = get_root_info_for_path(root_path); if (info == NULL) { LOGW("Unable to get root info for %s during fstab generation!", root_path); return; } MtdPartition *mtd = get_root_mtd_partition(root_path); if (mtd != NULL) { fprintf(file, "/dev/block/mtdblock%d ", mtd->device_index); } else { fprintf(file, "%s ", info->device); } fprintf(file, "%s ", info->mount_point); fprintf(file, "%s %s\n", info->filesystem, info->filesystem_options == NULL ? "rw" : info->filesystem_options); }
/* write_raw_image <src-image> <dest-root> */ static int cmd_write_raw_image(const char *name, void *cookie, int argc, const char *argv[]) { UNUSED(cookie); CHECK_WORDS(); if (argc != 2) { LOGE("Command %s requires exactly two arguments\n", name); return 1; } // Use 10% of the progress bar (20% post-verification) by default const char *src_root_path = argv[0]; const char *dst_root_path = argv[1]; ui_print("Writing %s...\n", dst_root_path); if (!gDidShowProgress) ui_show_progress(DEFAULT_IMAGE_PROGRESS_FRACTION, 0); /* Find the source image, which is probably in a package. */ if (!is_package_root_path(src_root_path)) { LOGE("Command %s: non-package source path \"%s\" not yet supported\n", name, src_root_path); return 255; } /* Get the package. */ char srcpathbuf[PATH_MAX]; const char *src_path; const ZipArchive *package; src_path = translate_package_root_path(src_root_path, srcpathbuf, sizeof(srcpathbuf), &package); if (src_path == NULL) { LOGE("Command %s: bad source path \"%s\"\n", name, src_root_path); return 1; } /* Get the entry. */ const ZipEntry *entry = mzFindZipEntry(package, src_path); if (entry == NULL) { LOGE("Missing file %s\n", src_path); return 1; } /* Unmount the destination root if it isn't already. */ int ret = ensure_root_path_unmounted(dst_root_path); if (ret < 0) { LOGE("Can't unmount %s\n", dst_root_path); return 1; } /* Open the partition for writing. */ const MtdPartition *partition = get_root_mtd_partition(dst_root_path); if (partition == NULL) { LOGE("Can't find %s\n", dst_root_path); return 1; } MtdWriteContext *context = mtd_write_partition(partition); if (context == NULL) { LOGE("Can't open %s\n", dst_root_path); return 1; } /* Extract and write the image. */ bool ok = mzProcessZipEntryContents(package, entry, write_raw_image_process_fn, context); if (!ok) { LOGE("Error writing %s\n", dst_root_path); mtd_write_close(context); return 1; } if (mtd_erase_blocks(context, -1) == (off_t) -1) { LOGE("Error finishing %s\n", dst_root_path); mtd_write_close(context); return -1; } if (mtd_write_close(context)) { LOGE("Error closing %s\n", dst_root_path); return -1; } return 0; }
int write_update_for_bootloader( const char *update, int update_length, int bitmap_width, int bitmap_height, int bitmap_bpp, const char *busy_bitmap, const char *fail_bitmap) { if (ensure_root_path_unmounted(CACHE_NAME)) { LOGE("Can't unmount %s\n", CACHE_NAME); return -1; } const MtdPartition *part = get_root_mtd_partition(CACHE_NAME); if (part == NULL) { LOGE("Can't find %s\n", CACHE_NAME); return -1; } MtdWriteContext *write = mtd_write_partition(part); if (write == NULL) { LOGE("Can't open %s\n(%s)\n", CACHE_NAME, strerror(errno)); return -1; } /* Write an invalid (zero) header first, to disable any previous * update and any other structured contents (like a filesystem), * and as a placeholder for the amount of space required. */ struct update_header header; memset(&header, 0, sizeof(header)); const ssize_t header_size = sizeof(header); if (mtd_write_data(write, (char*) &header, header_size) != header_size) { LOGE("Can't write header to %s\n(%s)\n", CACHE_NAME, strerror(errno)); mtd_write_close(write); return -1; } /* Write each section individually block-aligned, so we can write * each block independently without complicated buffering. */ memcpy(&header.MAGIC, UPDATE_MAGIC, UPDATE_MAGIC_SIZE); header.version = UPDATE_VERSION; header.size = header_size; off_t image_start_pos = mtd_erase_blocks(write, 0); header.image_length = update_length; if ((int) header.image_offset == -1 || mtd_write_data(write, update, update_length) != update_length) { LOGE("Can't write update to %s\n(%s)\n", CACHE_NAME, strerror(errno)); mtd_write_close(write); return -1; } off_t busy_start_pos = mtd_erase_blocks(write, 0); header.image_offset = mtd_find_write_start(write, image_start_pos); header.bitmap_width = bitmap_width; header.bitmap_height = bitmap_height; header.bitmap_bpp = bitmap_bpp; int bitmap_length = (bitmap_bpp + 7) / 8 * bitmap_width * bitmap_height; header.busy_bitmap_length = busy_bitmap != NULL ? bitmap_length : 0; if ((int) header.busy_bitmap_offset == -1 || mtd_write_data(write, busy_bitmap, bitmap_length) != bitmap_length) { LOGE("Can't write bitmap to %s\n(%s)\n", CACHE_NAME, strerror(errno)); mtd_write_close(write); return -1; } off_t fail_start_pos = mtd_erase_blocks(write, 0); header.busy_bitmap_offset = mtd_find_write_start(write, busy_start_pos); header.fail_bitmap_length = fail_bitmap != NULL ? bitmap_length : 0; if ((int) header.fail_bitmap_offset == -1 || mtd_write_data(write, fail_bitmap, bitmap_length) != bitmap_length) { LOGE("Can't write bitmap to %s\n(%s)\n", CACHE_NAME, strerror(errno)); mtd_write_close(write); return -1; } mtd_erase_blocks(write, 0); header.fail_bitmap_offset = mtd_find_write_start(write, fail_start_pos); /* Write the header last, after all the blocks it refers to, so that * when the magic number is installed everything is valid. */ if (mtd_write_close(write)) { LOGE("Can't finish writing %s\n(%s)\n", CACHE_NAME, strerror(errno)); return -1; } write = mtd_write_partition(part); if (write == NULL) { LOGE("Can't reopen %s\n(%s)\n", CACHE_NAME, strerror(errno)); return -1; } if (mtd_write_data(write, (char*) &header, header_size) != header_size) { LOGE("Can't rewrite header to %s\n(%s)\n", CACHE_NAME, strerror(errno)); mtd_write_close(write); return -1; } if (mtd_erase_blocks(write, 0) != image_start_pos) { LOGE("Misalignment rewriting %s\n(%s)\n", CACHE_NAME, strerror(errno)); mtd_write_close(write); return -1; } if (mtd_write_close(write)) { LOGE("Can't finish header of %s\n(%s)\n", CACHE_NAME, strerror(errno)); return -1; } return 0; }
int set_bootloader_message(const struct bootloader_message *in) { // INFO("Enter set_bootloader_message\n"); if(in->command[0] != 0) { LOGI("command:\n%s\n", in->command); LOGI("status:\n%s\n", in->status); LOGI("recovery:\n%s\n", in->recovery); } else LOGI("bootloader_message is empty\n"); size_t write_size; const MtdPartition *part = get_root_mtd_partition(MISC_NAME); if (part == NULL || mtd_partition_info(part, NULL, NULL, &write_size)) { LOGE("Can't find %s\n", MISC_NAME); return -1; } MtdReadContext *read = mtd_read_partition(part); if (read == NULL) { LOGE("Can't open %s\n(%s)\n", MISC_NAME, strerror(errno)); return -1; } //cmy: 以sector为单位 ssize_t size = write_size * MISC_PAGES; char data[size<<9];//cmy ssize_t r = mtd_read_data(read, data, size); if (r != size) LOGE("Can't read %s\n(%s)\n", MISC_NAME, strerror(errno)); mtd_read_close(read); if (r != size) return -1; memcpy(&data[(write_size<<9) * MISC_COMMAND_PAGE], in, sizeof(*in)); #ifdef LOG_VERBOSE printf("\n--- set_bootloader_message ---\n"); dump_data(data, size<<9); printf("\n"); #endif // INFO("\n--- set_bootloader_message ---\n"); // dump_data(data, size); // INFO("\n"); // CMY:由于底层写数据时会自动执行擦除操作,因些我们可以直接写数据而不考虑擦除动作 #if 1 MtdWriteContext *write = mtd_write_partition(part); if (write == NULL) { LOGE("Can't open %s\n(%s)\n", MISC_NAME, strerror(errno)); return -1; } LOGI("Write bootloader message\n"); if (mtd_write_data(write, data, size) != size) { LOGE("Can't write %s\n(%s)\n", MISC_NAME, strerror(errno)); mtd_write_close(write); return -1; } if (mtd_write_close(write)) { LOGE("Can't finish %s\n(%s)\n", MISC_NAME, strerror(errno)); return -1; } #endif LOGI("Set boot command \"%s\"\n", in->command[0] != 255 ? in->command : ""); return 0; }