blob: 389f1c9c6141f78ac91da2638c3c0c0007922b21 [file] [log] [blame]
Koushik Duttabec09952010-12-19 20:37:57 -08001#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>
22
23#include "bootloader.h"
24#include "common.h"
25#include "cutils/properties.h"
26#include "firmware.h"
27#include "install.h"
28#include "minui/minui.h"
29#include "minzip/DirUtil.h"
30#include "roots.h"
31#include "recovery_ui.h"
32
33#include "../../external/yaffs2/yaffs2/utils/mkyaffs2image.h"
34#include "../../external/yaffs2/yaffs2/utils/unyaffs.h"
35
36#include "extendedcommands.h"
37#include "nandroid.h"
38#include "mounts.h"
39#include "flashutils/flashutils.h"
40#include "edify/expr.h"
41#include "mtdutils/mtdutils.h"
42#include "mmcutils/mmcutils.h"
43//#include "edify/parser.h"
44
45Value* UIPrintFn(const char* name, State* state, int argc, Expr* argv[]) {
46 char** args = ReadVarArgs(state, argc, argv);
47 if (args == NULL) {
48 return NULL;
49 }
50
51 int size = 0;
52 int i;
53 for (i = 0; i < argc; ++i) {
54 size += strlen(args[i]);
55 }
56 char* buffer = malloc(size+1);
57 size = 0;
58 for (i = 0; i < argc; ++i) {
59 strcpy(buffer+size, args[i]);
60 size += strlen(args[i]);
61 free(args[i]);
62 }
63 free(args);
64 buffer[size] = '\0';
65
66 char* line = strtok(buffer, "\n");
67 while (line) {
68 ui_print("%s\n", line);
69 line = strtok(NULL, "\n");
70 }
71
72 return StringValue(buffer);
73}
74
75Value* RunProgramFn(const char* name, State* state, int argc, Expr* argv[]) {
76 if (argc < 1) {
77 return ErrorAbort(state, "%s() expects at least 1 arg", name);
78 }
79 char** args = ReadVarArgs(state, argc, argv);
80 if (args == NULL) {
81 return NULL;
82 }
83
84 char** args2 = malloc(sizeof(char*) * (argc+1));
85 memcpy(args2, args, sizeof(char*) * argc);
86 args2[argc] = NULL;
87
88 fprintf(stderr, "about to run program [%s] with %d args\n", args2[0], argc);
89
90 pid_t child = fork();
91 if (child == 0) {
92 execv(args2[0], args2);
93 fprintf(stderr, "run_program: execv failed: %s\n", strerror(errno));
94 _exit(1);
95 }
96 int status;
97 waitpid(child, &status, 0);
98 if (WIFEXITED(status)) {
99 if (WEXITSTATUS(status) != 0) {
100 fprintf(stderr, "run_program: child exited with status %d\n",
101 WEXITSTATUS(status));
102 }
103 } else if (WIFSIGNALED(status)) {
104 fprintf(stderr, "run_program: child terminated by signal %d\n",
105 WTERMSIG(status));
106 }
107
108 int i;
109 for (i = 0; i < argc; ++i) {
110 free(args[i]);
111 }
112 free(args);
113 free(args2);
114
115 char buffer[20];
116 sprintf(buffer, "%d", status);
117
118 return StringValue(strdup(buffer));
119}
120
121Value* FormatFn(const char* name, State* state, int argc, Expr* argv[]) {
122 char* result = NULL;
123 if (argc != 1) {
124 return ErrorAbort(state, "%s() expects 1 arg, got %d", name, argc);
125 }
126
127 char *path;
128 if (ReadArgs(state, argv, 1, &path) < 0) {
129 return NULL;
130 }
131
132 ui_print("Formatting %s...\n", path);
133 if (0 != format_volume(path)) {
134 free(path);
135 return StringValue(strdup(""));
136 }
Koushik Dutta33fd0d02011-02-27 12:42:24 -0800137
138 if (strcmp(path, "/data") == 0 && has_datadata()) {
139 ui_print("Formatting /datadata...\n", path);
140 if (0 != format_volume("/datadata")) {
141 free(path);
142 return StringValue(strdup(""));
143 }
Koushik Dutta7364e822011-04-23 19:01:16 -0700144 if (0 != format_volume("/sdcard/.android_secure")) {
145 free(path);
146 return StringValue(strdup(""));
147 }
Koushik Dutta33fd0d02011-02-27 12:42:24 -0800148 }
Koushik Duttabec09952010-12-19 20:37:57 -0800149
150done:
151 return StringValue(strdup(path));
152}
153
154Value* BackupFn(const char* name, State* state, int argc, Expr* argv[]) {
155 char* result = NULL;
156 if (argc != 1) {
157 return ErrorAbort(state, "%s() expects 1 args, got %d", name, argc);
158 }
159 char* path;
160 if (ReadArgs(state, argv, 1, &path) < 0) {
161 return NULL;
162 }
163
164 if (0 != nandroid_backup(path))
165 return StringValue(strdup(""));
166
167 return StringValue(strdup(path));
168}
169
170Value* RestoreFn(const char* name, State* state, int argc, Expr* argv[]) {
171 if (argc < 1) {
172 return ErrorAbort(state, "%s() expects at least 1 arg", name);
173 }
174 char** args = ReadVarArgs(state, argc, argv);
175 if (args == NULL) {
176 return NULL;
177 }
178
179 char** args2 = malloc(sizeof(char*) * (argc+1));
180 memcpy(args2, args, sizeof(char*) * argc);
181 args2[argc] = NULL;
182
183 char* path = strdup(args2[0]);
184 int restoreboot = 1;
185 int restoresystem = 1;
186 int restoredata = 1;
187 int restorecache = 1;
188 int restoresdext = 1;
189 int i;
190 for (i = 1; i < argc; i++)
191 {
192 if (args2[i] == NULL)
193 continue;
194 if (strcmp(args2[i], "noboot") == 0)
195 restoreboot = 0;
196 else if (strcmp(args2[i], "nosystem") == 0)
197 restoresystem = 0;
198 else if (strcmp(args2[i], "nodata") == 0)
199 restoredata = 0;
200 else if (strcmp(args2[i], "nocache") == 0)
201 restorecache = 0;
202 else if (strcmp(args2[i], "nosd-ext") == 0)
203 restoresdext = 0;
204 }
205
206 for (i = 0; i < argc; ++i) {
207 free(args[i]);
208 }
209 free(args);
210 free(args2);
211
Koushik Dutta5b7f34a2010-12-29 23:36:03 -0800212 if (0 != nandroid_restore(path, restoreboot, restoresystem, restoredata, restorecache, restoresdext, 0)) {
Koushik Duttabec09952010-12-19 20:37:57 -0800213 free(path);
214 return StringValue(strdup(""));
215 }
216
217 return StringValue(path);
218}
219
220Value* InstallZipFn(const char* name, State* state, int argc, Expr* argv[]) {
221 char* result = NULL;
222 if (argc != 1) {
223 return ErrorAbort(state, "%s() expects 1 args, got %d", name, argc);
224 }
225 char* path;
226 if (ReadArgs(state, argv, 1, &path) < 0) {
227 return NULL;
228 }
229
230 if (0 != install_zip(path))
231 return StringValue(strdup(""));
232
233 return StringValue(strdup(path));
234}
235
Koushik Dutta30a937a2011-09-05 21:14:06 -0700236Value* MountFn(const char* name, State* state, int argc, Expr* argv[]) {
237 char* result = NULL;
238 if (argc != 1) {
239 return ErrorAbort(state, "%s() expects 1 args, got %d", name, argc);
240 }
241 char* path;
242 if (ReadArgs(state, argv, 1, &path) < 0) {
243 return NULL;
244 }
245
246 if (0 != ensure_path_mounted(path))
247 return StringValue(strdup(""));
248
249 return StringValue(strdup(path));
250}
251
Koushik Duttabec09952010-12-19 20:37:57 -0800252void RegisterRecoveryHooks() {
Koushik Dutta30a937a2011-09-05 21:14:06 -0700253 RegisterFunction("mount", MountFn);
Koushik Duttabec09952010-12-19 20:37:57 -0800254 RegisterFunction("format", FormatFn);
255 RegisterFunction("ui_print", UIPrintFn);
256 RegisterFunction("run_program", RunProgramFn);
257 RegisterFunction("backup_rom", BackupFn);
258 RegisterFunction("restore_rom", RestoreFn);
259 RegisterFunction("install_zip", InstallZipFn);
260}
261
262static int hasInitializedEdify = 0;
263int run_script_from_buffer(char* script_data, int script_len, char* filename)
264{
265 if (!hasInitializedEdify) {
266 RegisterBuiltins();
267 RegisterRecoveryHooks();
268 FinishRegistration();
269 hasInitializedEdify = 1;
270 }
271
272 Expr* root;
273 int error_count = 0;
274 yy_scan_bytes(script_data, script_len);
275 int error = yyparse(&root, &error_count);
276 printf("parse returned %d; %d errors encountered\n", error, error_count);
277 if (error == 0 || error_count > 0) {
278 //ExprDump(0, root, buffer);
279
280 State state;
281 state.cookie = NULL;
282 state.script = script_data;
283 state.errmsg = NULL;
284
285 char* result = Evaluate(&state, root);
286 if (result == NULL) {
287 printf("result was NULL, message is: %s\n",
288 (state.errmsg == NULL ? "(NULL)" : state.errmsg));
289 free(state.errmsg);
290 return -1;
291 } else {
292 printf("result is [%s]\n", result);
293 }
294 }
295 return 0;
296}