#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include extern int __system(const char *command); #define BML_UNLOCK_ALL 0x8A29 ///< unlock all partition RO -> RW static int restore_internal(const char* bml, const char* filename) { char buf[4096]; int dstfd, srcfd, bytes_read, bytes_written, total_read = 0; if (filename == NULL) srcfd = 0; else { srcfd = open(filename, O_RDONLY | O_LARGEFILE); if (srcfd < 0) return 2; } dstfd = open(bml, O_RDWR | O_LARGEFILE); if (dstfd < 0) return 3; if (ioctl(dstfd, BML_UNLOCK_ALL, 0)) return 4; do { total_read += bytes_read = read(srcfd, buf, 4096); if (!bytes_read) break; if (bytes_read < 4096) memset(&buf[bytes_read], 0, 4096 - bytes_read); if (write(dstfd, buf, 4096) < 4096) return 5; } while(bytes_read == 4096); close(dstfd); close(srcfd); return 0; } int cmd_bml_restore_raw_partition(const char *partition, const char *filename) { if (strcmp(partition, "boot") != 0 && strcmp(partition, "recovery") != 0) return 6; // always restore boot, regardless of whether recovery or boot is flashed. // this is because boot and recovery are the same on some samsung phones. int ret = restore_internal("/dev/block/bml7", filename); if (ret != 0) return ret; if (strcmp(partition, "recovery") == 0) ret = restore_internal("/dev/block/bml8", filename); return ret; } int cmd_bml_backup_raw_partition(const char *partition, const char *filename) { char* bml; if (strcmp("boot", partition) == 0) bml = "/dev/block/bml7"; else if (strcmp("recovery", partition) == 0) bml = "/dev/block/bml8"; else { printf("Invalid partition.\n"); return -1; } int ch; FILE *in; FILE *out; int val = 0; char buf[512]; unsigned sz = 0; unsigned i; int ret = -1; char *in_file = bml; in = fopen ( in_file, "r" ); if (in == NULL) goto ERROR3; out = fopen ( out_file, "w" ); if (out == NULL) goto ERROR2; fseek(in, 0L, SEEK_END); sz = ftell(in); fseek(in, 0L, SEEK_SET); if (sz % 512) { while ( ( ch = fgetc ( in ) ) != EOF ) fputc ( ch, out ); } else { for (i=0; i< (sz/512); i++) { if ((fread(buf, 512, 1, in)) != 1) goto ERROR1; if ((fwrite(buf, 512, 1, out)) != 1) goto ERROR1; } } fsync(out); ret = 0; ERROR1: fclose ( out ); ERROR2: fclose ( in ); ERROR3: return ret; } int cmd_bml_erase_raw_partition(const char *partition) { // TODO: implement raw wipe return 0; } int cmd_bml_erase_partition(const char *partition, const char *filesystem) { return -1; } int cmd_bml_mount_partition(const char *partition, const char *mount_point, const char *filesystem, int read_only) { return -1; } int cmd_bml_get_partition_device(const char *partition, char *device) { return -1; }