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