#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "../libcrecovery/common.h" static int restore_internal(const char* bml, const char* filename) { char buf[4096]; int dstfd, srcfd, bytes_read, 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 && strcmp(partition, "recoveryonly") != 0 && partition[0] != '/') return 6; int ret = -1; if (strcmp(partition, "recoveryonly") != 0) { // always restore boot, regardless of whether recovery or boot is flashed. // this is because boot and recovery are the same on some samsung phones. // unless of course, recoveryonly is explictly chosen (bml8) ret = restore_internal(BOARD_BML_BOOT, filename); if (ret != 0) return ret; } if (strcmp(partition, "recovery") == 0 || strcmp(partition, "recoveryonly") == 0) ret = restore_internal(BOARD_BML_RECOVERY, filename); // support explicitly provided device paths if (partition[0] == '/') ret = restore_internal(partition, filename); return ret; } int cmd_bml_backup_raw_partition(const char *partition, const char *out_file) { const char* bml; if (strcmp("boot", partition) == 0) bml = BOARD_BML_BOOT; else if (strcmp("recovery", partition) == 0) bml = BOARD_BML_RECOVERY; else if (partition[0] == '/') { // support explicitly provided device paths bml = partition; } else { printf("Invalid partition.\n"); return -1; } int ch; FILE *in; FILE *out; char buf[512]; unsigned sz = 0; unsigned i; int ret = -1; const 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(fileno(out)); ret = 0; ERROR1: fclose ( out ); ERROR2: fclose ( in ); ERROR3: return ret; } int cmd_bml_erase_raw_partition(const char *partition __unused) { // TODO: implement raw wipe return 0; } int cmd_bml_erase_partition(const char *partition __unused, const char *filesystem __unused) { return -1; } int cmd_bml_mount_partition(const char *partition __unused, const char *mount_point __unused, const char *filesystem __unused, int read_only __unused) { return -1; } int cmd_bml_get_partition_device(const char *partition __unused, char *device __unused) { return -1; } int format_rfs_device (const char *device, const char *path) { const char *fatsize = "32"; const char *sectorsize = "1"; if (strcmp(path, "/datadata") == 0 || strcmp(path, "/cache") == 0) { fatsize = "16"; } // Just in case /data sector size needs to be altered else if (strcmp(path, "/data") == 0 ) { sectorsize = "1"; } // dump 10KB of zeros to partition before format due to fat.format bug char cmd[PATH_MAX]; sprintf(cmd, "/sbin/dd if=/dev/zero of=%s bs=4096 count=10", device); if(__system(cmd)) { printf("failure while zeroing rfs partition.\n"); return -1; } // Run fat.format sprintf(cmd, "/sbin/fat.format -F %s -S 4096 -s %s %s", fatsize, sectorsize, device); if(__system(cmd)) { printf("failure while running fat.format\n"); return -1; } return 0; }