blob: 4c7c49d0309e94eaf1f8695324e25ce2aa8959f9 [file] [log] [blame]
Dees_Troy51a0e822012-09-05 15:24:24 -04001#include <ctype.h>
2#include <errno.h>
3#include <fcntl.h>
4#include <getopt.h>
5#include <limits.h>
6#include <linux/input.h>
7#include <stdio.h>
8#include <stdlib.h>
9#include <string.h>
10#include <sys/reboot.h>
11#include <sys/types.h>
12#include <time.h>
13#include <unistd.h>
14
15#include <sys/wait.h>
16#include <sys/limits.h>
17#include <dirent.h>
18#include <sys/stat.h>
19
20#include <signal.h>
21#include <sys/wait.h>
Dees_Troy51a0e822012-09-05 15:24:24 -040022
Conn O'Griofad9201042014-03-25 01:26:49 +000023#include <bmlutils.h>
Dees_Troy51a0e822012-09-05 15:24:24 -040024
Ethan Yonkerbcc502c2014-11-10 11:22:10 -060025#include "../libcrecovery/common.h"
Dees_Troy51a0e822012-09-05 15:24:24 -040026
27static int restore_internal(const char* bml, const char* filename)
28{
29 char buf[4096];
30 int dstfd, srcfd, bytes_read, bytes_written, total_read = 0;
31 if (filename == NULL)
32 srcfd = 0;
33 else {
34 srcfd = open(filename, O_RDONLY | O_LARGEFILE);
35 if (srcfd < 0)
36 return 2;
37 }
38 dstfd = open(bml, O_RDWR | O_LARGEFILE);
39 if (dstfd < 0)
40 return 3;
41 if (ioctl(dstfd, BML_UNLOCK_ALL, 0))
42 return 4;
43 do {
44 total_read += bytes_read = read(srcfd, buf, 4096);
45 if (!bytes_read)
46 break;
47 if (bytes_read < 4096)
48 memset(&buf[bytes_read], 0, 4096 - bytes_read);
49 if (write(dstfd, buf, 4096) < 4096)
50 return 5;
51 } while(bytes_read == 4096);
52
53 close(dstfd);
54 close(srcfd);
55
56 return 0;
57}
58
59int cmd_bml_restore_raw_partition(const char *partition, const char *filename)
60{
61 if (strcmp(partition, "boot") != 0 && strcmp(partition, "recovery") != 0 && strcmp(partition, "recoveryonly") != 0 && partition[0] != '/')
62 return 6;
63
64 int ret = -1;
65 if (strcmp(partition, "recoveryonly") != 0) {
66 // always restore boot, regardless of whether recovery or boot is flashed.
67 // this is because boot and recovery are the same on some samsung phones.
68 // unless of course, recoveryonly is explictly chosen (bml8)
69 ret = restore_internal(BOARD_BML_BOOT, filename);
70 if (ret != 0)
71 return ret;
72 }
73
74 if (strcmp(partition, "recovery") == 0 || strcmp(partition, "recoveryonly") == 0)
75 ret = restore_internal(BOARD_BML_RECOVERY, filename);
76
77 // support explicitly provided device paths
78 if (partition[0] == '/')
79 ret = restore_internal(partition, filename);
80 return ret;
81}
82
83int cmd_bml_backup_raw_partition(const char *partition, const char *out_file)
84{
85 char* bml;
86 if (strcmp("boot", partition) == 0)
87 bml = BOARD_BML_BOOT;
88 else if (strcmp("recovery", partition) == 0)
89 bml = BOARD_BML_RECOVERY;
90 else if (partition[0] == '/') {
91 // support explicitly provided device paths
92 bml = partition;
93 }
94 else {
95 printf("Invalid partition.\n");
96 return -1;
97 }
98
99 int ch;
100 FILE *in;
101 FILE *out;
102 int val = 0;
103 char buf[512];
104 unsigned sz = 0;
105 unsigned i;
106 int ret = -1;
107 char *in_file = bml;
108
109 in = fopen ( in_file, "r" );
110 if (in == NULL)
111 goto ERROR3;
112
113 out = fopen ( out_file, "w" );
114 if (out == NULL)
115 goto ERROR2;
116
117 fseek(in, 0L, SEEK_END);
118 sz = ftell(in);
119 fseek(in, 0L, SEEK_SET);
120
121 if (sz % 512)
122 {
123 while ( ( ch = fgetc ( in ) ) != EOF )
124 fputc ( ch, out );
125 }
126 else
127 {
128 for (i=0; i< (sz/512); i++)
129 {
130 if ((fread(buf, 512, 1, in)) != 1)
131 goto ERROR1;
132 if ((fwrite(buf, 512, 1, out)) != 1)
133 goto ERROR1;
134 }
135 }
136
137 fsync(out);
138 ret = 0;
139ERROR1:
140 fclose ( out );
141ERROR2:
142 fclose ( in );
143ERROR3:
144 return ret;
145}
146
147int cmd_bml_erase_raw_partition(const char *partition)
148{
149 // TODO: implement raw wipe
150 return 0;
151}
152
153int cmd_bml_erase_partition(const char *partition, const char *filesystem)
154{
155 return -1;
156}
157
158int cmd_bml_mount_partition(const char *partition, const char *mount_point, const char *filesystem, int read_only)
159{
160 return -1;
161}
162
163int cmd_bml_get_partition_device(const char *partition, char *device)
164{
165 return -1;
166}
167
168int format_rfs_device (const char *device, const char *path) {
169 const char *fatsize = "32";
170 const char *sectorsize = "1";
171
172 if (strcmp(path, "/datadata") == 0 || strcmp(path, "/cache") == 0) {
173 fatsize = "16";
174 }
175
176 // Just in case /data sector size needs to be altered
177 else if (strcmp(path, "/data") == 0 ) {
178 sectorsize = "1";
179 }
180
181 // dump 10KB of zeros to partition before format due to fat.format bug
182 char cmd[PATH_MAX];
183
184 sprintf(cmd, "/sbin/dd if=/dev/zero of=%s bs=4096 count=10", device);
185 if(__system(cmd)) {
186 printf("failure while zeroing rfs partition.\n");
187 return -1;
188 }
189
190 // Run fat.format
191 sprintf(cmd, "/sbin/fat.format -F %s -S 4096 -s %s %s", fatsize, sectorsize, device);
192 if(__system(cmd)) {
193 printf("failure while running fat.format\n");
194 return -1;
195 }
196
197 return 0;
198}