blob: 54b67f51342939118c9c2e66138c8ee6b68e210f [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
Dees_Troy51a0e822012-09-05 15:24:24 -040023#define BML_UNLOCK_ALL 0x8A29 ///< unlock all partition RO -> RW
24
25#ifndef BOARD_BML_BOOT
26#define BOARD_BML_BOOT "/dev/block/bml7"
27#endif
28
29#ifndef BOARD_BML_RECOVERY
30#define BOARD_BML_RECOVERY "/dev/block/bml8"
31#endif
32
33#undef _PATH_BSHELL
34#define _PATH_BSHELL "/sbin/sh"
35
36int __system(const char *command)
37{
38 pid_t pid;
39 sig_t intsave, quitsave;
40 sigset_t mask, omask;
41 int pstat;
42 char *argp[] = {"sh", "-c", NULL, NULL};
43
44 if (!command) /* just checking... */
45 return(1);
46
47 argp[2] = (char *)command;
48
49 sigemptyset(&mask);
50 sigaddset(&mask, SIGCHLD);
51 sigprocmask(SIG_BLOCK, &mask, &omask);
52 switch (pid = vfork()) {
53 case -1: /* error */
54 sigprocmask(SIG_SETMASK, &omask, NULL);
55 return(-1);
56 case 0: /* child */
57 sigprocmask(SIG_SETMASK, &omask, NULL);
58 execve(_PATH_BSHELL, argp, environ);
59 _exit(127);
60 }
61
62 intsave = (sig_t) bsd_signal(SIGINT, SIG_IGN);
63 quitsave = (sig_t) bsd_signal(SIGQUIT, SIG_IGN);
64 pid = waitpid(pid, (int *)&pstat, 0);
65 sigprocmask(SIG_SETMASK, &omask, NULL);
66 (void)bsd_signal(SIGINT, intsave);
67 (void)bsd_signal(SIGQUIT, quitsave);
68 return (pid == -1 ? -1 : pstat);
69}
70
71static struct pid {
72 struct pid *next;
73 FILE *fp;
74 pid_t pid;
75} *pidlist;
76
77
78static int restore_internal(const char* bml, const char* filename)
79{
80 char buf[4096];
81 int dstfd, srcfd, bytes_read, bytes_written, total_read = 0;
82 if (filename == NULL)
83 srcfd = 0;
84 else {
85 srcfd = open(filename, O_RDONLY | O_LARGEFILE);
86 if (srcfd < 0)
87 return 2;
88 }
89 dstfd = open(bml, O_RDWR | O_LARGEFILE);
90 if (dstfd < 0)
91 return 3;
92 if (ioctl(dstfd, BML_UNLOCK_ALL, 0))
93 return 4;
94 do {
95 total_read += bytes_read = read(srcfd, buf, 4096);
96 if (!bytes_read)
97 break;
98 if (bytes_read < 4096)
99 memset(&buf[bytes_read], 0, 4096 - bytes_read);
100 if (write(dstfd, buf, 4096) < 4096)
101 return 5;
102 } while(bytes_read == 4096);
103
104 close(dstfd);
105 close(srcfd);
106
107 return 0;
108}
109
110int cmd_bml_restore_raw_partition(const char *partition, const char *filename)
111{
112 if (strcmp(partition, "boot") != 0 && strcmp(partition, "recovery") != 0 && strcmp(partition, "recoveryonly") != 0 && partition[0] != '/')
113 return 6;
114
115 int ret = -1;
116 if (strcmp(partition, "recoveryonly") != 0) {
117 // always restore boot, regardless of whether recovery or boot is flashed.
118 // this is because boot and recovery are the same on some samsung phones.
119 // unless of course, recoveryonly is explictly chosen (bml8)
120 ret = restore_internal(BOARD_BML_BOOT, filename);
121 if (ret != 0)
122 return ret;
123 }
124
125 if (strcmp(partition, "recovery") == 0 || strcmp(partition, "recoveryonly") == 0)
126 ret = restore_internal(BOARD_BML_RECOVERY, filename);
127
128 // support explicitly provided device paths
129 if (partition[0] == '/')
130 ret = restore_internal(partition, filename);
131 return ret;
132}
133
134int cmd_bml_backup_raw_partition(const char *partition, const char *out_file)
135{
136 char* bml;
137 if (strcmp("boot", partition) == 0)
138 bml = BOARD_BML_BOOT;
139 else if (strcmp("recovery", partition) == 0)
140 bml = BOARD_BML_RECOVERY;
141 else if (partition[0] == '/') {
142 // support explicitly provided device paths
143 bml = partition;
144 }
145 else {
146 printf("Invalid partition.\n");
147 return -1;
148 }
149
150 int ch;
151 FILE *in;
152 FILE *out;
153 int val = 0;
154 char buf[512];
155 unsigned sz = 0;
156 unsigned i;
157 int ret = -1;
158 char *in_file = bml;
159
160 in = fopen ( in_file, "r" );
161 if (in == NULL)
162 goto ERROR3;
163
164 out = fopen ( out_file, "w" );
165 if (out == NULL)
166 goto ERROR2;
167
168 fseek(in, 0L, SEEK_END);
169 sz = ftell(in);
170 fseek(in, 0L, SEEK_SET);
171
172 if (sz % 512)
173 {
174 while ( ( ch = fgetc ( in ) ) != EOF )
175 fputc ( ch, out );
176 }
177 else
178 {
179 for (i=0; i< (sz/512); i++)
180 {
181 if ((fread(buf, 512, 1, in)) != 1)
182 goto ERROR1;
183 if ((fwrite(buf, 512, 1, out)) != 1)
184 goto ERROR1;
185 }
186 }
187
188 fsync(out);
189 ret = 0;
190ERROR1:
191 fclose ( out );
192ERROR2:
193 fclose ( in );
194ERROR3:
195 return ret;
196}
197
198int cmd_bml_erase_raw_partition(const char *partition)
199{
200 // TODO: implement raw wipe
201 return 0;
202}
203
204int cmd_bml_erase_partition(const char *partition, const char *filesystem)
205{
206 return -1;
207}
208
209int cmd_bml_mount_partition(const char *partition, const char *mount_point, const char *filesystem, int read_only)
210{
211 return -1;
212}
213
214int cmd_bml_get_partition_device(const char *partition, char *device)
215{
216 return -1;
217}
218
219int format_rfs_device (const char *device, const char *path) {
220 const char *fatsize = "32";
221 const char *sectorsize = "1";
222
223 if (strcmp(path, "/datadata") == 0 || strcmp(path, "/cache") == 0) {
224 fatsize = "16";
225 }
226
227 // Just in case /data sector size needs to be altered
228 else if (strcmp(path, "/data") == 0 ) {
229 sectorsize = "1";
230 }
231
232 // dump 10KB of zeros to partition before format due to fat.format bug
233 char cmd[PATH_MAX];
234
235 sprintf(cmd, "/sbin/dd if=/dev/zero of=%s bs=4096 count=10", device);
236 if(__system(cmd)) {
237 printf("failure while zeroing rfs partition.\n");
238 return -1;
239 }
240
241 // Run fat.format
242 sprintf(cmd, "/sbin/fat.format -F %s -S 4096 -s %s %s", fatsize, sectorsize, device);
243 if(__system(cmd)) {
244 printf("failure while running fat.format\n");
245 return -1;
246 }
247
248 return 0;
249}