blob: d6e5e4f4ff2e2eba3ae4eb1fa9073569fa9d777d [file] [log] [blame]
Koushik K. Dutta6060e5c2010-02-11 22:27:06 -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
Koushik K. Duttae9234872010-02-12 00:43:24 -080015#include <sys/wait.h>
16#include <sys/limits.h>
17#include <dirent.h>
Koushik K. Dutta49f56892010-02-25 14:51:05 -080018#include <sys/stat.h>
Koushik K. Duttae9234872010-02-12 00:43:24 -080019
Koushik K. Dutta33370db2010-02-25 11:39:07 -080020#include <signal.h>
21#include <sys/wait.h>
22
Koushik K. Dutta6060e5c2010-02-11 22:27:06 -080023#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
Koushik K. Duttaf68aaaf2010-03-07 13:39:21 -080033#include "commands.h"
34#include "amend/amend.h"
35
Koushik K. Duttaa85d7cc2010-03-12 17:00:58 -080036#include "../../external/yaffs2/yaffs2/utils/mkyaffs2image.h"
Koushik K. Dutta54305a82010-03-12 17:43:26 -080037#include "../../external/yaffs2/yaffs2/utils/unyaffs.h"
Koushik K. Duttaa85d7cc2010-03-12 17:00:58 -080038
Koushik K. Duttaee57bbc2010-03-12 23:21:12 -080039#include "extendedcommands.h"
40#include "nandroid.h"
41
Koushik K. Dutta6060e5c2010-02-11 22:27:06 -080042int signature_check_enabled = 1;
43int script_assert_enabled = 1;
Koushik K. Duttabcdd0032010-02-21 21:10:25 -080044static const char *SDCARD_PACKAGE_FILE = "SDCARD:update.zip";
Koushik K. Dutta6060e5c2010-02-11 22:27:06 -080045
46void
47toggle_signature_check()
48{
49 signature_check_enabled = !signature_check_enabled;
50 ui_print("Signature Check: %s\n", signature_check_enabled ? "Enabled" : "Disabled");
51}
52
53void toggle_script_asserts()
54{
55 script_assert_enabled = !script_assert_enabled;
Koushik K. Duttae9234872010-02-12 00:43:24 -080056 ui_print("Script Asserts: %s\n", script_assert_enabled ? "Enabled" : "Disabled");
57}
58
Koushik K. Duttaea46fe22010-03-08 02:58:04 -080059int install_zip(const char* packagefilepath)
Koushik K. Duttae9234872010-02-12 00:43:24 -080060{
Koushik K. Duttabcdd0032010-02-21 21:10:25 -080061 ui_print("\n-- Installing: %s\n", packagefilepath);
Koushik Dutta5aaa8232010-07-20 16:23:18 -070062#ifndef BOARD_HAS_NO_MISC_PARTITION
Koushik K. Duttabcdd0032010-02-21 21:10:25 -080063 set_sdcard_update_bootloader_message();
Koushik Dutta5aaa8232010-07-20 16:23:18 -070064#endif
Koushik K. Duttabcdd0032010-02-21 21:10:25 -080065 int status = install_package(packagefilepath);
Koushik K. Duttaf3534d02010-04-18 18:06:24 -070066 ui_reset_progress();
Koushik K. Duttabcdd0032010-02-21 21:10:25 -080067 if (status != INSTALL_SUCCESS) {
68 ui_set_background(BACKGROUND_ICON_ERROR);
69 ui_print("Installation aborted.\n");
Koushik K. Duttaea46fe22010-03-08 02:58:04 -080070 return 1;
Steve Kondik4123b582010-11-14 03:18:40 -050071 }
Koushik Dutta5aaa8232010-07-20 16:23:18 -070072#ifndef BOARD_HAS_NO_MISC_PARTITION
Koushik K. Dutta79ce82c2010-02-25 12:03:17 -080073 if (firmware_update_pending()) {
74 ui_print("\nReboot via menu to complete\ninstallation.\n");
Koushik K. Dutta001c5b52010-02-25 14:53:57 -080075 }
Koushik Dutta5aaa8232010-07-20 16:23:18 -070076#endif
Koushik K. Dutta001c5b52010-02-25 14:53:57 -080077 ui_set_background(BACKGROUND_ICON_NONE);
Koushik K. Dutta99fb6fe2010-03-03 00:42:58 -080078 ui_print("\nInstall from sdcard complete.\n");
Koushik K. Duttaea46fe22010-03-08 02:58:04 -080079 return 0;
Koushik K. Duttabcdd0032010-02-21 21:10:25 -080080}
81
82char* INSTALL_MENU_ITEMS[] = { "apply sdcard:update.zip",
83 "choose zip from sdcard",
84 "toggle signature verification",
85 "toggle script asserts",
86 NULL };
87#define ITEM_APPLY_SDCARD 0
88#define ITEM_CHOOSE_ZIP 1
89#define ITEM_SIG_CHECK 2
90#define ITEM_ASSERTS 3
91
92void show_install_update_menu()
93{
94 static char* headers[] = { "Apply update from .zip file on SD card",
95 "",
Steve Kondik4123b582010-11-14 03:18:40 -050096 NULL
Koushik K. Duttabcdd0032010-02-21 21:10:25 -080097 };
98 for (;;)
99 {
100 int chosen_item = get_menu_selection(headers, INSTALL_MENU_ITEMS, 0);
101 switch (chosen_item)
102 {
103 case ITEM_ASSERTS:
104 toggle_script_asserts();
105 break;
106 case ITEM_SIG_CHECK:
107 toggle_signature_check();
108 break;
109 case ITEM_APPLY_SDCARD:
Koushik Duttad63eaef2010-07-14 21:01:21 -0700110 {
111 if (confirm_selection("Confirm install?", "Yes - Install /sdcard/update.zip"))
112 install_zip(SDCARD_PACKAGE_FILE);
Koushik K. Duttabcdd0032010-02-21 21:10:25 -0800113 break;
Koushik Duttad63eaef2010-07-14 21:01:21 -0700114 }
Koushik K. Duttabcdd0032010-02-21 21:10:25 -0800115 case ITEM_CHOOSE_ZIP:
116 show_choose_zip_menu();
117 break;
118 default:
119 return;
120 }
Steve Kondik4123b582010-11-14 03:18:40 -0500121
Koushik K. Duttabcdd0032010-02-21 21:10:25 -0800122 }
123}
124
Koushik K. Dutta1d53c4e2010-04-02 16:46:21 -0700125void free_string_array(char** array)
126{
127 if (array == NULL)
128 return;
129 char* cursor = array[0];
130 int i = 0;
131 while (cursor != NULL)
132 {
133 free(cursor);
134 cursor = array[++i];
135 }
136 free(array);
137}
138
Koushik K. Dutta49f56892010-02-25 14:51:05 -0800139char** gather_files(const char* directory, const char* fileExtensionOrDirectory, int* numFiles)
Koushik K. Duttabcdd0032010-02-21 21:10:25 -0800140{
Koushik K. Duttae9234872010-02-12 00:43:24 -0800141 char path[PATH_MAX] = "";
142 DIR *dir;
143 struct dirent *de;
144 int total = 0;
145 int i;
Koushik K. Duttaee57bbc2010-03-12 23:21:12 -0800146 char** files = NULL;
Koushik K. Dutta001c5b52010-02-25 14:53:57 -0800147 int pass;
148 *numFiles = 0;
149 int dirLen = strlen(directory);
Koushik K. Duttae9234872010-02-12 00:43:24 -0800150
Koushik K. Duttabcdd0032010-02-21 21:10:25 -0800151 dir = opendir(directory);
152 if (dir == NULL) {
153 ui_print("Couldn't open directory.\n");
154 return NULL;
155 }
Steve Kondik4123b582010-11-14 03:18:40 -0500156
Koushik K. Duttaee57bbc2010-03-12 23:21:12 -0800157 int extension_length = 0;
Koushik K. Dutta001c5b52010-02-25 14:53:57 -0800158 if (fileExtensionOrDirectory != NULL)
159 extension_length = strlen(fileExtensionOrDirectory);
Steve Kondik4123b582010-11-14 03:18:40 -0500160
Koushik K. Dutta001c5b52010-02-25 14:53:57 -0800161 int isCounting = 1;
162 i = 0;
163 for (pass = 0; pass < 2; pass++) {
164 while ((de=readdir(dir)) != NULL) {
165 // skip hidden files
166 if (de->d_name[0] == '.')
167 continue;
Steve Kondik4123b582010-11-14 03:18:40 -0500168
Koushik K. Dutta001c5b52010-02-25 14:53:57 -0800169 // NULL means that we are gathering directories, so skip this
170 if (fileExtensionOrDirectory != NULL)
171 {
172 // make sure that we can have the desired extension (prevent seg fault)
173 if (strlen(de->d_name) < extension_length)
174 continue;
175 // compare the extension
176 if (strcmp(de->d_name + strlen(de->d_name) - extension_length, fileExtensionOrDirectory) != 0)
177 continue;
178 }
179 else
180 {
181 struct stat info;
Koushik K. Dutta1d53c4e2010-04-02 16:46:21 -0700182 char fullFileName[PATH_MAX];
Koushik K. Dutta001c5b52010-02-25 14:53:57 -0800183 strcpy(fullFileName, directory);
184 strcat(fullFileName, de->d_name);
185 stat(fullFileName, &info);
Koushik K. Dutta001c5b52010-02-25 14:53:57 -0800186 // make sure it is a directory
187 if (!(S_ISDIR(info.st_mode)))
188 continue;
189 }
Steve Kondik4123b582010-11-14 03:18:40 -0500190
Koushik K. Dutta001c5b52010-02-25 14:53:57 -0800191 if (pass == 0)
192 {
193 total++;
194 continue;
195 }
Steve Kondik4123b582010-11-14 03:18:40 -0500196
Koushik K. Dutta49f56892010-02-25 14:51:05 -0800197 files[i] = (char*) malloc(dirLen + strlen(de->d_name) + 2);
198 strcpy(files[i], directory);
199 strcat(files[i], de->d_name);
Koushik K. Dutta001c5b52010-02-25 14:53:57 -0800200 if (fileExtensionOrDirectory == NULL)
201 strcat(files[i], "/");
202 i++;
203 }
204 if (pass == 1)
205 break;
206 if (total == 0)
207 break;
208 rewinddir(dir);
209 *numFiles = total;
210 files = (char**) malloc((total+1)*sizeof(char*));
211 files[total]=NULL;
212 }
Koushik K. Dutta49f56892010-02-25 14:51:05 -0800213
214 if(closedir(dir) < 0) {
215 LOGE("Failed to close directory.");
Koushik K. Duttabcdd0032010-02-21 21:10:25 -0800216 }
217
218 if (total==0) {
Koushik K. Duttabcdd0032010-02-21 21:10:25 -0800219 return NULL;
220 }
221
Koushik Dutta1e8aaba2010-07-01 00:23:25 -0700222 // sort the result
223 if (files != NULL) {
224 for (i = 0; i < total; i++) {
225 int curMax = -1;
226 int j;
227 for (j = 0; j < total - i; j++) {
228 if (curMax == -1 || strcmp(files[curMax], files[j]) < 0)
229 curMax = j;
230 }
231 char* temp = files[curMax];
232 files[curMax] = files[total - i - 1];
233 files[total - i - 1] = temp;
234 }
235 }
236
Koushik K. Dutta001c5b52010-02-25 14:53:57 -0800237 return files;
Koushik K. Dutta49f56892010-02-25 14:51:05 -0800238}
Koushik K. Duttabcdd0032010-02-21 21:10:25 -0800239
Koushik K. Dutta49f56892010-02-25 14:51:05 -0800240// pass in NULL for fileExtensionOrDirectory and you will get a directory chooser
241char* choose_file_menu(const char* directory, const char* fileExtensionOrDirectory, const char* headers[])
242{
243 char path[PATH_MAX] = "";
244 DIR *dir;
245 struct dirent *de;
246 int numFiles = 0;
Koushik K. Dutta001c5b52010-02-25 14:53:57 -0800247 int numDirs = 0;
Koushik K. Dutta49f56892010-02-25 14:51:05 -0800248 int i;
Koushik K. Dutta1d53c4e2010-04-02 16:46:21 -0700249 char* return_value = NULL;
Koushik K. Dutta001c5b52010-02-25 14:53:57 -0800250 int dir_len = strlen(directory);
Koushik K. Duttabcdd0032010-02-21 21:10:25 -0800251
Koushik K. Dutta001c5b52010-02-25 14:53:57 -0800252 char** files = gather_files(directory, fileExtensionOrDirectory, &numFiles);
Koushik K. Duttaee57bbc2010-03-12 23:21:12 -0800253 char** dirs = NULL;
Koushik K. Dutta001c5b52010-02-25 14:53:57 -0800254 if (fileExtensionOrDirectory != NULL)
255 dirs = gather_files(directory, NULL, &numDirs);
256 int total = numDirs + numFiles;
257 if (total == 0)
258 {
259 ui_print("No files found.\n");
Koushik K. Dutta001c5b52010-02-25 14:53:57 -0800260 }
Koushik K. Dutta1d53c4e2010-04-02 16:46:21 -0700261 else
Koushik K. Dutta001c5b52010-02-25 14:53:57 -0800262 {
Koushik K. Dutta1d53c4e2010-04-02 16:46:21 -0700263 char** list = (char**) malloc((total + 1) * sizeof(char*));
264 list[total] = NULL;
Koushik K. Duttabcdd0032010-02-21 21:10:25 -0800265
Koushik K. Duttabcdd0032010-02-21 21:10:25 -0800266
Koushik K. Dutta1d53c4e2010-04-02 16:46:21 -0700267 for (i = 0 ; i < numDirs; i++)
Koushik K. Dutta001c5b52010-02-25 14:53:57 -0800268 {
Koushik K. Dutta1d53c4e2010-04-02 16:46:21 -0700269 list[i] = strdup(dirs[i] + dir_len);
270 }
271
272 for (i = 0 ; i < numFiles; i++)
273 {
274 list[numDirs + i] = strdup(files[i] + dir_len);
275 }
276
277 for (;;)
278 {
279 int chosen_item = get_menu_selection(headers, list, 0);
280 if (chosen_item == GO_BACK)
281 break;
282 static char ret[PATH_MAX];
283 if (chosen_item < numDirs)
284 {
285 char* subret = choose_file_menu(dirs[chosen_item], fileExtensionOrDirectory, headers);
286 if (subret != NULL)
287 {
288 strcpy(ret, subret);
289 return_value = ret;
290 break;
291 }
292 continue;
Steve Kondik4123b582010-11-14 03:18:40 -0500293 }
Koushik K. Dutta1d53c4e2010-04-02 16:46:21 -0700294 strcpy(ret, files[chosen_item - numDirs]);
295 return_value = ret;
296 break;
297 }
298 free_string_array(list);
Koushik K. Dutta981b0cd2010-02-22 08:53:34 -0800299 }
Koushik K. Dutta1d53c4e2010-04-02 16:46:21 -0700300
301 free_string_array(files);
302 free_string_array(dirs);
303 return return_value;
Koushik K. Duttabcdd0032010-02-21 21:10:25 -0800304}
305
306void show_choose_zip_menu()
307{
Koushik K. Duttae9234872010-02-12 00:43:24 -0800308 if (ensure_root_path_mounted("SDCARD:") != 0) {
309 LOGE ("Can't mount /sdcard\n");
310 return;
311 }
312
Koushik K. Duttabcdd0032010-02-21 21:10:25 -0800313 static char* headers[] = { "Choose a zip to apply",
314 "",
Steve Kondik4123b582010-11-14 03:18:40 -0500315 NULL
Koushik K. Duttabcdd0032010-02-21 21:10:25 -0800316 };
Steve Kondik4123b582010-11-14 03:18:40 -0500317
Koushik K. Duttabcdd0032010-02-21 21:10:25 -0800318 char* file = choose_file_menu("/sdcard/", ".zip", headers);
319 if (file == NULL)
320 return;
321 char sdcard_package_file[1024];
322 strcpy(sdcard_package_file, "SDCARD:");
323 strcat(sdcard_package_file, file + strlen("/sdcard/"));
Koushik Duttad63eaef2010-07-14 21:01:21 -0700324 static char* confirm_install = "Confirm install?";
325 static char confirm[PATH_MAX];
326 sprintf(confirm, "Yes - Install %s", basename(file));
327 if (confirm_selection(confirm_install, confirm))
328 install_zip(sdcard_package_file);
Koushik K. Duttabcdd0032010-02-21 21:10:25 -0800329}
330
Koushik K. Duttabcdd0032010-02-21 21:10:25 -0800331void show_nandroid_restore_menu()
332{
Koushik K. Dutta54305a82010-03-12 17:43:26 -0800333 if (ensure_root_path_mounted("SDCARD:") != 0) {
334 LOGE ("Can't mount /sdcard\n");
Koushik K. Duttaee57bbc2010-03-12 23:21:12 -0800335 return;
Koushik K. Dutta54305a82010-03-12 17:43:26 -0800336 }
Steve Kondik4123b582010-11-14 03:18:40 -0500337
Koushik K. Duttabcdd0032010-02-21 21:10:25 -0800338 static char* headers[] = { "Choose an image to restore",
339 "",
Steve Kondik4123b582010-11-14 03:18:40 -0500340 NULL
Koushik K. Duttabcdd0032010-02-21 21:10:25 -0800341 };
Koushik K. Duttae9234872010-02-12 00:43:24 -0800342
Koushik K. Dutta49f56892010-02-25 14:51:05 -0800343 char* file = choose_file_menu("/sdcard/clockworkmod/backup/", NULL, headers);
Koushik K. Duttabcdd0032010-02-21 21:10:25 -0800344 if (file == NULL)
345 return;
Koushik Duttad63eaef2010-07-14 21:01:21 -0700346
347 if (confirm_selection("Confirm restore?", "Yes - Restore"))
348 nandroid_restore(file, 1, 1, 1, 1, 1);
Koushik K. Dutta03173782010-02-26 14:14:23 -0800349}
350
Koushik K. Duttab9546a82010-03-14 22:42:30 -0700351void show_mount_usb_storage_menu()
Koushik K. Dutta03173782010-02-26 14:14:23 -0800352{
Koushik Dutta598cfc72010-06-20 09:42:47 -0700353 char command[PATH_MAX];
Koushik Dutta19447c02010-11-10 10:40:44 -0800354 sprintf(command, "echo %s > /sys/devices/platform/usb_mass_storage/lun0/file", BOARD_SDCARD_DEVICE_PRIMARY);
Koushik Dutta598cfc72010-06-20 09:42:47 -0700355 __system(command);
Koushik K. Dutta03173782010-02-26 14:14:23 -0800356 static char* headers[] = { "USB Mass Storage device",
357 "Leaving this menu unmount",
358 "your SD card from your PC.",
359 "",
Steve Kondik4123b582010-11-14 03:18:40 -0500360 NULL
Koushik K. Dutta03173782010-02-26 14:14:23 -0800361 };
Steve Kondik4123b582010-11-14 03:18:40 -0500362
Koushik K. Dutta03173782010-02-26 14:14:23 -0800363 static char* list[] = { "Unmount", NULL };
Steve Kondik4123b582010-11-14 03:18:40 -0500364
Koushik K. Dutta03173782010-02-26 14:14:23 -0800365 for (;;)
366 {
367 int chosen_item = get_menu_selection(headers, list, 0);
368 if (chosen_item == GO_BACK || chosen_item == 0)
369 break;
370 }
Steve Kondik4123b582010-11-14 03:18:40 -0500371
Koushik K. Duttaf7215942010-03-16 13:34:51 -0700372 __system("echo '' > /sys/devices/platform/usb_mass_storage/lun0/file");
373 __system("echo 0 > /sys/devices/platform/usb_mass_storage/lun0/enable");
Koushik K. Duttae81cb752010-02-26 17:44:33 -0800374}
Koushik K. Duttaf68aaaf2010-03-07 13:39:21 -0800375
Koushik Duttad63eaef2010-07-14 21:01:21 -0700376int confirm_selection(const char* title, const char* confirm)
Koushik K. Dutta16f0b492010-03-19 14:37:11 -0700377{
Koushik Duttaceddcd52010-08-23 16:13:14 -0700378 struct stat info;
379 if (0 == stat("/sdcard/clockworkmod/.no_confirm", &info))
380 return 1;
381
Koushik Duttad63eaef2010-07-14 21:01:21 -0700382 char* confirm_headers[] = { title, " THIS CAN NOT BE UNDONE.", "", NULL };
383 char* items[] = { "No",
384 "No",
385 "No",
386 "No",
387 "No",
388 "No",
389 "No",
Koushik Duttaecd32fa2010-07-14 18:38:02 -0700390 confirm, //" Yes -- wipe partition", // [7
Koushik Duttad63eaef2010-07-14 21:01:21 -0700391 "No",
392 "No",
393 "No",
Koushik K. Dutta16f0b492010-03-19 14:37:11 -0700394 NULL };
395
Koushik Duttad63eaef2010-07-14 21:01:21 -0700396 int chosen_item = get_menu_selection(confirm_headers, items, 0);
Koushik K. Dutta16f0b492010-03-19 14:37:11 -0700397 return chosen_item == 7;
398}
399
Koushik Dutta19447c02010-11-10 10:40:44 -0800400int format_unknown_device(const char* root)
Koushik K. Dutta3f995392010-03-30 23:29:43 -0700401{
Koushik K. Duttaf3534d02010-04-18 18:06:24 -0700402 // if this is SDEXT:, don't worry about it.
403 if (0 == strcmp(root, "SDEXT:"))
404 {
405 struct stat st;
Koushik Dutta19447c02010-11-10 10:40:44 -0800406 if (0 != stat(BOARD_SDEXT_DEVICE, &st))
Koushik K. Duttaf3534d02010-04-18 18:06:24 -0700407 {
408 ui_print("No app2sd partition found. Skipping format of /sd-ext.\n");
409 return 0;
410 }
411 }
Koushik Dutta2f73e582010-04-18 16:00:21 -0700412
Koushik K. Dutta3f995392010-03-30 23:29:43 -0700413 char path[PATH_MAX];
414 translate_root_path(root, path, PATH_MAX);
415 if (0 != ensure_root_path_mounted(root))
416 {
417 ui_print("Error mounting %s!\n", path);
Koushik Duttacd44ab92010-06-23 00:02:14 -0700418 ui_print("Skipping format...\n");
419 return 0;
Koushik K. Dutta3f995392010-03-30 23:29:43 -0700420 }
421
422 static char tmp[PATH_MAX];
423 sprintf(tmp, "rm -rf %s/*", path);
424 __system(tmp);
425 sprintf(tmp, "rm -rf %s/.*", path);
426 __system(tmp);
Steve Kondik4123b582010-11-14 03:18:40 -0500427
Koushik K. Dutta3f995392010-03-30 23:29:43 -0700428 ensure_root_path_unmounted(root);
429 return 0;
430}
431
432#define MOUNTABLE_COUNT 5
433#define MTD_COUNT 4
434#define MMC_COUNT 2
Koushik K. Duttab9546a82010-03-14 22:42:30 -0700435
Koushik K. Dutta5899ac92010-03-19 13:34:36 -0700436void show_partition_menu()
Koushik K. Duttab9546a82010-03-14 22:42:30 -0700437{
Koushik Duttaceddcd52010-08-23 16:13:14 -0700438 static char* headers[] = { "Mounts and Storage Menu",
Koushik K. Duttab9546a82010-03-14 22:42:30 -0700439 "",
Steve Kondik4123b582010-11-14 03:18:40 -0500440 NULL
Koushik K. Duttab9546a82010-03-14 22:42:30 -0700441 };
442
443 typedef char* string;
Steve Kondik4123b582010-11-14 03:18:40 -0500444 string mounts[MOUNTABLE_COUNT][3] = {
Koushik K. Dutta16f0b492010-03-19 14:37:11 -0700445 { "mount /system", "unmount /system", "SYSTEM:" },
446 { "mount /data", "unmount /data", "DATA:" },
447 { "mount /cache", "unmount /cache", "CACHE:" },
Koushik K. Dutta3f995392010-03-30 23:29:43 -0700448 { "mount /sdcard", "unmount /sdcard", "SDCARD:" },
449 { "mount /sd-ext", "unmount /sd-ext", "SDEXT:" }
Koushik K. Duttab9546a82010-03-14 22:42:30 -0700450 };
Steve Kondik4123b582010-11-14 03:18:40 -0500451
Koushik K. Dutta16f0b492010-03-19 14:37:11 -0700452 string mtds[MTD_COUNT][2] = {
Koushik K. Dutta3f995392010-03-30 23:29:43 -0700453 { "format boot", "BOOT:" },
454 { "format system", "SYSTEM:" },
455 { "format data", "DATA:" },
456 { "format cache", "CACHE:" },
457 };
Steve Kondik4123b582010-11-14 03:18:40 -0500458
Koushik K. Dutta3f995392010-03-30 23:29:43 -0700459 string mmcs[MMC_COUNT][3] = {
460 { "format sdcard", "SDCARD:" },
Steve Kondik4123b582010-11-14 03:18:40 -0500461 { "format sd-ext", "SDEXT:" }
Koushik K. Dutta16f0b492010-03-19 14:37:11 -0700462 };
Steve Kondik4123b582010-11-14 03:18:40 -0500463
Koushik Duttad63eaef2010-07-14 21:01:21 -0700464 static char* confirm_format = "Confirm format?";
Koushik Duttaecd32fa2010-07-14 18:38:02 -0700465 static char* confirm = "Yes - Format";
Steve Kondik4123b582010-11-14 03:18:40 -0500466
Koushik K. Duttab9546a82010-03-14 22:42:30 -0700467 for (;;)
468 {
Koushik K. Dutta5899ac92010-03-19 13:34:36 -0700469 int ismounted[MOUNTABLE_COUNT];
Koushik K. Duttab9546a82010-03-14 22:42:30 -0700470 int i;
Koushik K. Dutta3f995392010-03-30 23:29:43 -0700471 static string options[MOUNTABLE_COUNT + MTD_COUNT + MMC_COUNT + 1 + 1]; // mountables, format mtds, format mmcs, usb storage, null
Koushik K. Dutta5899ac92010-03-19 13:34:36 -0700472 for (i = 0; i < MOUNTABLE_COUNT; i++)
Koushik K. Duttab9546a82010-03-14 22:42:30 -0700473 {
Koushik K. Dutta16f0b492010-03-19 14:37:11 -0700474 ismounted[i] = is_root_path_mounted(mounts[i][2]);
Koushik K. Duttab9546a82010-03-14 22:42:30 -0700475 options[i] = ismounted[i] ? mounts[i][1] : mounts[i][0];
476 }
Steve Kondik4123b582010-11-14 03:18:40 -0500477
Koushik K. Dutta5899ac92010-03-19 13:34:36 -0700478 for (i = 0; i < MTD_COUNT; i++)
479 {
Koushik K. Dutta16f0b492010-03-19 14:37:11 -0700480 options[MOUNTABLE_COUNT + i] = mtds[i][0];
Koushik K. Dutta5899ac92010-03-19 13:34:36 -0700481 }
Steve Kondik4123b582010-11-14 03:18:40 -0500482
Koushik K. Dutta3f995392010-03-30 23:29:43 -0700483 for (i = 0; i < MMC_COUNT; i++)
484 {
485 options[MOUNTABLE_COUNT + MTD_COUNT + i] = mmcs[i][0];
486 }
Steve Kondik4123b582010-11-14 03:18:40 -0500487
Koushik K. Dutta3f995392010-03-30 23:29:43 -0700488 options[MOUNTABLE_COUNT + MTD_COUNT + MMC_COUNT] = "mount USB storage";
489 options[MOUNTABLE_COUNT + MTD_COUNT + MMC_COUNT + 1] = NULL;
Steve Kondik4123b582010-11-14 03:18:40 -0500490
Koushik K. Duttab9546a82010-03-14 22:42:30 -0700491 int chosen_item = get_menu_selection(headers, options, 0);
492 if (chosen_item == GO_BACK)
493 break;
Koushik K. Dutta3f995392010-03-30 23:29:43 -0700494 if (chosen_item == MOUNTABLE_COUNT + MTD_COUNT + MMC_COUNT)
Koushik K. Duttab9546a82010-03-14 22:42:30 -0700495 {
496 show_mount_usb_storage_menu();
497 }
Koushik K. Dutta5899ac92010-03-19 13:34:36 -0700498 else if (chosen_item < MOUNTABLE_COUNT)
Koushik K. Duttab9546a82010-03-14 22:42:30 -0700499 {
500 if (ismounted[chosen_item])
501 {
Koushik K. Dutta16f0b492010-03-19 14:37:11 -0700502 if (0 != ensure_root_path_unmounted(mounts[chosen_item][2]))
503 ui_print("Error unmounting %s!\n", mounts[chosen_item][2]);
Koushik K. Duttab9546a82010-03-14 22:42:30 -0700504 }
505 else
506 {
Koushik K. Dutta16f0b492010-03-19 14:37:11 -0700507 if (0 != ensure_root_path_mounted(mounts[chosen_item][2]))
508 ui_print("Error mounting %s!\n", mounts[chosen_item][2]);
Koushik K. Duttab9546a82010-03-14 22:42:30 -0700509 }
510 }
Koushik K. Dutta5899ac92010-03-19 13:34:36 -0700511 else if (chosen_item < MOUNTABLE_COUNT + MTD_COUNT)
512 {
513 chosen_item = chosen_item - MOUNTABLE_COUNT;
Koushik Duttaecd32fa2010-07-14 18:38:02 -0700514 if (!confirm_selection(confirm_format, confirm))
Koushik K. Dutta16f0b492010-03-19 14:37:11 -0700515 continue;
516 ui_print("Formatting %s...\n", mtds[chosen_item][1]);
Koushik K. Dutta3f995392010-03-30 23:29:43 -0700517 if (0 != format_root_device(mtds[chosen_item][1]))
518 ui_print("Error formatting %s!\n", mtds[chosen_item][1]);
519 else
520 ui_print("Done.\n");
521 }
522 else if (chosen_item < MOUNTABLE_COUNT + MTD_COUNT + MMC_COUNT)
523 {
524 chosen_item = chosen_item - MOUNTABLE_COUNT - MTD_COUNT;
Koushik Duttaecd32fa2010-07-14 18:38:02 -0700525 if (!confirm_selection(confirm_format, confirm))
Koushik K. Dutta3f995392010-03-30 23:29:43 -0700526 continue;
527 ui_print("Formatting %s...\n", mmcs[chosen_item][1]);
Koushik Dutta19447c02010-11-10 10:40:44 -0800528 if (0 != format_unknown_device(mmcs[chosen_item][1]))
Koushik K. Dutta3f995392010-03-30 23:29:43 -0700529 ui_print("Error formatting %s!\n", mmcs[chosen_item][1]);
530 else
531 ui_print("Done.\n");
Koushik K. Dutta5899ac92010-03-19 13:34:36 -0700532 }
Koushik K. Duttab9546a82010-03-14 22:42:30 -0700533 }
534}
535
Koushik K. Dutta72a1db62010-03-07 14:10:26 -0800536#define EXTENDEDCOMMAND_SCRIPT "/cache/recovery/extendedcommand"
537
538int extendedcommand_file_exists()
Koushik K. Duttaf68aaaf2010-03-07 13:39:21 -0800539{
Koushik K. Duttaf68aaaf2010-03-07 13:39:21 -0800540 struct stat file_info;
Koushik K. Dutta72a1db62010-03-07 14:10:26 -0800541 return 0 == stat(EXTENDEDCOMMAND_SCRIPT, &file_info);
542}
543
Koushik K. Dutta3836f722010-03-11 22:17:43 -0800544int run_script_from_buffer(char* script_data, int script_len, char* filename)
Koushik K. Dutta72a1db62010-03-07 14:10:26 -0800545{
Koushik K. Duttaf68aaaf2010-03-07 13:39:21 -0800546 /* Parse the script. Note that the script and parse tree are never freed.
547 */
548 const AmCommandList *commands = parseAmendScript(script_data, script_len);
549 if (commands == NULL) {
550 printf("Syntax error in update script\n");
551 return 1;
552 } else {
Koushik K. Dutta72a1db62010-03-07 14:10:26 -0800553 printf("Parsed %.*s\n", script_len, filename);
Koushik K. Duttaf68aaaf2010-03-07 13:39:21 -0800554 }
555
556 /* Execute the script.
557 */
558 int ret = execCommandList((ExecContext *)1, commands);
559 if (ret != 0) {
560 int num = ret;
Koushik K. Duttaee57bbc2010-03-12 23:21:12 -0800561 char *line = NULL, *next = script_data;
Koushik K. Duttaf68aaaf2010-03-07 13:39:21 -0800562 while (next != NULL && ret-- > 0) {
563 line = next;
564 next = memchr(line, '\n', script_data + script_len - line);
565 if (next != NULL) *next++ = '\0';
566 }
567 printf("Failure at line %d:\n%s\n", num, next ? line : "(not found)");
568 return 1;
Steve Kondik4123b582010-11-14 03:18:40 -0500569 }
570
Koushik K. Duttaf68aaaf2010-03-07 13:39:21 -0800571 return 0;
572}
Koushik K. Dutta72a1db62010-03-07 14:10:26 -0800573
Koushik K. Dutta6771aca2010-04-03 23:28:39 -0700574int run_script(char* filename)
Koushik K. Dutta3836f722010-03-11 22:17:43 -0800575{
576 struct stat file_info;
577 if (0 != stat(filename, &file_info)) {
578 printf("Error executing stat on file: %s\n", filename);
579 return 1;
580 }
Steve Kondik4123b582010-11-14 03:18:40 -0500581
Koushik K. Dutta3836f722010-03-11 22:17:43 -0800582 int script_len = file_info.st_size;
Koushik K. Dutta707fa6d2010-03-23 11:44:33 -0700583 char* script_data = (char*)malloc(script_len + 1);
Koushik K. Dutta3836f722010-03-11 22:17:43 -0800584 FILE *file = fopen(filename, "rb");
585 fread(script_data, script_len, 1, file);
Koushik K. Dutta707fa6d2010-03-23 11:44:33 -0700586 // supposedly not necessary, but let's be safe.
587 script_data[script_len] = '\0';
Koushik K. Dutta3836f722010-03-11 22:17:43 -0800588 fclose(file);
Koushik Duttae25908b2010-06-21 08:16:19 -0700589 LOGI("Running script:\n");
590 LOGI("\n%s\n", script_data);
Koushik K. Dutta3836f722010-03-11 22:17:43 -0800591
Koushik K. Duttaf3534d02010-04-18 18:06:24 -0700592 int ret = run_script_from_buffer(script_data, script_len, filename);
Koushik K. Dutta1d53c4e2010-04-02 16:46:21 -0700593 free(script_data);
594 return ret;
Koushik K. Dutta3836f722010-03-11 22:17:43 -0800595}
596
Koushik K. Dutta72a1db62010-03-07 14:10:26 -0800597int run_and_remove_extendedcommand()
598{
Koushik K. Dutta6771aca2010-04-03 23:28:39 -0700599 char tmp[PATH_MAX];
600 sprintf(tmp, "cp %s /tmp/%s", EXTENDEDCOMMAND_SCRIPT, basename(EXTENDEDCOMMAND_SCRIPT));
601 __system(tmp);
602 remove(EXTENDEDCOMMAND_SCRIPT);
Koushik K. Dutta3a25cf52010-03-08 19:22:41 -0800603 int i = 0;
604 for (i = 20; i > 0; i--) {
605 ui_print("Waiting for SD Card to mount (%ds)\n", i);
606 if (ensure_root_path_mounted("SDCARD:") == 0) {
607 ui_print("SD Card mounted...\n");
608 break;
609 }
610 sleep(1);
611 }
Koushik Dutta92077c12010-07-15 00:10:08 -0700612 remove("/sdcard/clockworkmod/.recoverycheckpoint");
Koushik K. Dutta3a25cf52010-03-08 19:22:41 -0800613 if (i == 0) {
614 ui_print("Timed out waiting for SD card... continuing anyways.");
615 }
Steve Kondik4123b582010-11-14 03:18:40 -0500616
Koushik K. Dutta6771aca2010-04-03 23:28:39 -0700617 sprintf(tmp, "/tmp/%s", basename(EXTENDEDCOMMAND_SCRIPT));
618 return run_script(tmp);
Koushik K. Dutta72a1db62010-03-07 14:10:26 -0800619}
620
621int amend_main(int argc, char** argv)
622{
Steve Kondik4123b582010-11-14 03:18:40 -0500623 if (argc != 2)
Koushik K. Dutta72a1db62010-03-07 14:10:26 -0800624 {
625 printf("Usage: amend <script>\n");
626 return 0;
627 }
628
629 RecoveryCommandContext ctx = { NULL };
630 if (register_update_commands(&ctx)) {
631 LOGE("Can't install update commands\n");
632 }
Koushik K. Dutta6771aca2010-04-03 23:28:39 -0700633 return run_script(argv[1]);
Koushik K. Dutta5306db52010-03-08 14:09:35 -0800634}
Koushik K. Dutta5899ac92010-03-19 13:34:36 -0700635
Koushik K. Duttafe84a7f2010-03-25 18:19:23 -0700636void show_nandroid_advanced_restore_menu()
637{
638 if (ensure_root_path_mounted("SDCARD:") != 0) {
639 LOGE ("Can't mount /sdcard\n");
640 return;
641 }
642
643 static char* advancedheaders[] = { "Choose an image to restore",
644 "",
645 "Choose an image to restore",
646 "first. The next menu will",
647 "you more options.",
648 "",
649 NULL
650 };
651
652 char* file = choose_file_menu("/sdcard/clockworkmod/backup/", NULL, advancedheaders);
653 if (file == NULL)
654 return;
655
656 static char* headers[] = { "Nandroid Advanced Restore",
657 "",
658 NULL
659 };
660
661 static char* list[] = { "Restore boot",
662 "Restore system",
663 "Restore data",
664 "Restore cache",
Koushik K. Dutta68b01902010-04-01 12:20:39 -0700665 "Restore sd-ext",
Koushik K. Duttafe84a7f2010-03-25 18:19:23 -0700666 NULL
667 };
668
Koushik Duttad63eaef2010-07-14 21:01:21 -0700669
670 static char* confirm_restore = "Confirm restore?";
671
Koushik K. Duttafe84a7f2010-03-25 18:19:23 -0700672 int chosen_item = get_menu_selection(headers, list, 0);
673 switch (chosen_item)
674 {
675 case 0:
Koushik Duttad63eaef2010-07-14 21:01:21 -0700676 if (confirm_selection(confirm_restore, "Yes - Restore boot"))
677 nandroid_restore(file, 1, 0, 0, 0, 0);
Koushik K. Duttafe84a7f2010-03-25 18:19:23 -0700678 break;
679 case 1:
Koushik Duttad63eaef2010-07-14 21:01:21 -0700680 if (confirm_selection(confirm_restore, "Yes - Restore system"))
681 nandroid_restore(file, 0, 1, 0, 0, 0);
Koushik K. Duttafe84a7f2010-03-25 18:19:23 -0700682 break;
683 case 2:
Koushik Duttad63eaef2010-07-14 21:01:21 -0700684 if (confirm_selection(confirm_restore, "Yes - Restore data"))
685 nandroid_restore(file, 0, 0, 1, 0, 0);
Koushik K. Duttafe84a7f2010-03-25 18:19:23 -0700686 break;
687 case 3:
Koushik Duttad63eaef2010-07-14 21:01:21 -0700688 if (confirm_selection(confirm_restore, "Yes - Restore cache"))
689 nandroid_restore(file, 0, 0, 0, 1, 0);
Koushik K. Duttafe84a7f2010-03-25 18:19:23 -0700690 break;
Koushik Dutta2f73e582010-04-18 16:00:21 -0700691 case 4:
Koushik Duttad63eaef2010-07-14 21:01:21 -0700692 if (confirm_selection(confirm_restore, "Yes - Restore sd-ext"))
693 nandroid_restore(file, 0, 0, 0, 0, 1);
Koushik Dutta2f73e582010-04-18 16:00:21 -0700694 break;
Koushik K. Duttafe84a7f2010-03-25 18:19:23 -0700695 }
696}
697
Koushik K. Dutta5899ac92010-03-19 13:34:36 -0700698void show_nandroid_menu()
699{
700 static char* headers[] = { "Nandroid",
701 "",
Steve Kondik4123b582010-11-14 03:18:40 -0500702 NULL
Koushik K. Dutta5899ac92010-03-19 13:34:36 -0700703 };
704
Steve Kondik4123b582010-11-14 03:18:40 -0500705 static char* list[] = { "Backup",
Koushik K. Dutta5899ac92010-03-19 13:34:36 -0700706 "Restore",
Koushik K. Duttafe84a7f2010-03-25 18:19:23 -0700707 "Advanced Restore",
Koushik K. Dutta5899ac92010-03-19 13:34:36 -0700708 NULL
709 };
710
711 int chosen_item = get_menu_selection(headers, list, 0);
712 switch (chosen_item)
713 {
714 case 0:
715 {
Koushik K. Dutta5899ac92010-03-19 13:34:36 -0700716 char backup_path[PATH_MAX];
Koushik K. Dutta6a26e7c2010-03-27 15:26:11 -0700717 time_t t = time(NULL);
718 struct tm *tmp = localtime(&t);
719 if (tmp == NULL)
720 {
721 struct timeval tp;
722 gettimeofday(&tp, NULL);
723 sprintf(backup_path, "/sdcard/clockworkmod/backup/%d", tp.tv_sec);
724 }
725 else
726 {
727 strftime(backup_path, sizeof(backup_path), "/sdcard/clockworkmod/backup/%F.%H.%M.%S", tmp);
728 }
Koushik K. Dutta5899ac92010-03-19 13:34:36 -0700729 nandroid_backup(backup_path);
730 }
731 break;
732 case 1:
733 show_nandroid_restore_menu();
734 break;
Koushik K. Duttafe84a7f2010-03-25 18:19:23 -0700735 case 2:
736 show_nandroid_advanced_restore_menu();
737 break;
Koushik K. Dutta5899ac92010-03-19 13:34:36 -0700738 }
Koushik K. Duttaa496b512010-03-19 14:51:45 -0700739}
740
Koushik Duttafd1579b2010-05-01 12:46:55 -0700741void wipe_battery_stats()
742{
743 ensure_root_path_mounted("DATA:");
744 remove("/data/system/batterystats.bin");
745 ensure_root_path_unmounted("DATA:");
746}
747
Koushik K. Duttaa496b512010-03-19 14:51:45 -0700748void show_advanced_menu()
749{
750 static char* headers[] = { "Advanced and Debugging Menu",
751 "",
752 NULL
753 };
754
Koushik K. Dutta7fe4d7b2010-04-06 23:04:52 -0700755 static char* list[] = { "Reboot Recovery",
Koushik Dutta49af23c2010-06-21 13:45:51 -0700756 "Wipe Dalvik Cache",
Koushik Duttafd1579b2010-05-01 12:46:55 -0700757 "Wipe Battery Stats",
Koushik Dutta598cfc72010-06-20 09:42:47 -0700758 "Report Error",
Koushik K. Dutta7fe4d7b2010-04-06 23:04:52 -0700759 "Key Test",
Koushik Duttae17a78d2010-08-29 12:35:10 -0700760#ifndef BOARD_HAS_SMALL_RECOVERY
Koushik Duttaceddcd52010-08-23 16:13:14 -0700761 "Partition SD Card",
762 "Fix Permissions",
Koushik Duttae17a78d2010-08-29 12:35:10 -0700763#endif
Koushik K. Duttaa496b512010-03-19 14:51:45 -0700764 NULL
765 };
766
767 for (;;)
768 {
769 int chosen_item = get_menu_selection(headers, list, 0);
770 if (chosen_item == GO_BACK)
771 break;
772 switch (chosen_item)
773 {
774 case 0:
Koushik K. Dutta7fe4d7b2010-04-06 23:04:52 -0700775 __reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, LINUX_REBOOT_CMD_RESTART2, "recovery");
776 break;
777 case 1:
Koushik Duttad63eaef2010-07-14 21:01:21 -0700778 {
Koushik Dutta49af23c2010-06-21 13:45:51 -0700779 if (0 != ensure_root_path_mounted("DATA:"))
780 break;
Koushik Dutta6c7745d2010-08-07 12:17:13 -0700781 ensure_root_path_mounted("SDEXT:");
782 ensure_root_path_mounted("CACHE:");
783 if (confirm_selection( "Confirm wipe?", "Yes - Wipe Dalvik Cache")) {
Koushik Duttad63eaef2010-07-14 21:01:21 -0700784 __system("rm -r /data/dalvik-cache");
Koushik Dutta6c7745d2010-08-07 12:17:13 -0700785 __system("rm -r /cache/dalvik-cache");
786 __system("rm -r /sd-ext/dalvik-cache");
787 }
Koushik Dutta49af23c2010-06-21 13:45:51 -0700788 ensure_root_path_unmounted("DATA:");
Koushik Dutta6c7745d2010-08-07 12:17:13 -0700789 ui_print("Dalvik Cache wiped.\n");
Koushik Duttafd1579b2010-05-01 12:46:55 -0700790 break;
Koushik Duttad63eaef2010-07-14 21:01:21 -0700791 }
Koushik Duttafd1579b2010-05-01 12:46:55 -0700792 case 2:
Koushik Duttad63eaef2010-07-14 21:01:21 -0700793 {
794 if (confirm_selection( "Confirm wipe?", "Yes - Wipe Battery Stats"))
795 wipe_battery_stats();
Koushik Dutta598cfc72010-06-20 09:42:47 -0700796 break;
Koushik Duttad63eaef2010-07-14 21:01:21 -0700797 }
Koushik Dutta598cfc72010-06-20 09:42:47 -0700798 case 3:
Koushik Dutta49af23c2010-06-21 13:45:51 -0700799 handle_failure(1);
800 break;
801 case 4:
Koushik K. Duttaa496b512010-03-19 14:51:45 -0700802 {
803 ui_print("Outputting key codes.\n");
804 ui_print("Go back to end debugging.\n");
805 int key;
806 int action;
807 do
808 {
809 key = ui_wait_key();
810 action = device_handle_key(key, 1);
811 ui_print("Key: %d\n", key);
812 }
813 while (action != GO_BACK);
Koushik Dutta56606a22010-08-23 16:15:33 -0700814 break;
Koushik K. Duttaa496b512010-03-19 14:51:45 -0700815 }
Koushik Duttaf0e31b82010-08-17 16:55:38 -0700816 case 5:
817 {
Koushik Duttaceddcd52010-08-23 16:13:14 -0700818 static char* ext_sizes[] = { "128M",
819 "256M",
820 "512M",
821 "1024M",
822 NULL };
823
824 static char* swap_sizes[] = { "0M",
825 "32M",
826 "64M",
827 "128M",
828 "256M",
829 NULL };
830
831 static char* ext_headers[] = { "Ext Size", "", NULL };
832 static char* swap_headers[] = { "Swap Size", "", NULL };
833
834 int ext_size = get_menu_selection(ext_headers, ext_sizes, 0);
835 if (ext_size == GO_BACK)
836 continue;
Steve Kondik4123b582010-11-14 03:18:40 -0500837
Koushik Duttaceddcd52010-08-23 16:13:14 -0700838 int swap_size = get_menu_selection(swap_headers, swap_sizes, 0);
839 if (swap_size == GO_BACK)
840 continue;
841
842 char sddevice[256];
843 const RootInfo *ri = get_root_info_for_path("SDCARD:");
844 strcpy(sddevice, ri->device);
845 // we only want the mmcblk, not the partition
846 sddevice[strlen("/dev/block/mmcblkX")] = NULL;
847 char cmd[PATH_MAX];
848 setenv("SDPATH", sddevice, 1);
849 sprintf(cmd, "sdparted -es %s -ss %s -efs ext3 -s", ext_sizes[ext_size], swap_sizes[swap_size]);
850 ui_print("Partitioning SD Card... please wait...\n");
851 if (0 == __system(cmd))
852 ui_print("Done!\n");
853 else
854 ui_print("An error occured while partitioning your SD Card. Please see /tmp/recovery.log for more details.\n");
Koushik Dutta56606a22010-08-23 16:15:33 -0700855 break;
Koushik Duttaf0e31b82010-08-17 16:55:38 -0700856 }
Koushik Dutta38e8b2b2010-08-17 22:21:53 -0700857 case 6:
858 {
Koushik Duttaceddcd52010-08-23 16:13:14 -0700859 ensure_root_path_mounted("SYSTEM:");
860 ensure_root_path_mounted("DATA:");
861 ui_print("Fixing permissions...\n");
862 __system("fix_permissions");
863 ui_print("Done!\n");
Koushik Dutta56606a22010-08-23 16:15:33 -0700864 break;
Koushik Dutta38e8b2b2010-08-17 22:21:53 -0700865 }
Koushik K. Duttaa496b512010-03-19 14:51:45 -0700866 }
867 }
Koushik Dutta14239d22010-06-14 15:02:48 -0700868}
869
870void write_fstab_root(char *root_path, FILE *file)
871{
872 RootInfo *info = get_root_info_for_path(root_path);
Koushik Duttaa6522b32010-06-20 13:16:06 -0700873 if (info == NULL) {
874 LOGW("Unable to get root info for %s during fstab generation!", root_path);
Koushik Dutta598cfc72010-06-20 09:42:47 -0700875 return;
Koushik Duttaa6522b32010-06-20 13:16:06 -0700876 }
Koushik Dutta19447c02010-11-10 10:40:44 -0800877 char device[PATH_MAX];
878 int ret = get_root_partition_device(root_path, device);
879 if (ret == 0)
Koushik Dutta14239d22010-06-14 15:02:48 -0700880 {
Koushik Dutta19447c02010-11-10 10:40:44 -0800881 fprintf(file, "%s ", device);
Koushik Dutta14239d22010-06-14 15:02:48 -0700882 }
883 else
884 {
Koushik Dutta19447c02010-11-10 10:40:44 -0800885 fprintf(file, "%s ", info->device);
Koushik Dutta14239d22010-06-14 15:02:48 -0700886 }
Steve Kondik4123b582010-11-14 03:18:40 -0500887
Koushik Dutta14239d22010-06-14 15:02:48 -0700888 fprintf(file, "%s ", info->mount_point);
Steve Kondik4123b582010-11-14 03:18:40 -0500889 fprintf(file, "%s %s\n", info->filesystem, info->filesystem_options == NULL ? "rw" : info->filesystem_options);
Koushik Dutta14239d22010-06-14 15:02:48 -0700890}
891
892void create_fstab()
893{
Koushik Duttacd44ab92010-06-23 00:02:14 -0700894 __system("touch /etc/mtab");
Koushik Dutta14239d22010-06-14 15:02:48 -0700895 FILE *file = fopen("/etc/fstab", "w");
Koushik Duttaa6522b32010-06-20 13:16:06 -0700896 if (file == NULL) {
897 LOGW("Unable to create /etc/fstab!");
Koushik Dutta598cfc72010-06-20 09:42:47 -0700898 return;
Koushik Duttaa6522b32010-06-20 13:16:06 -0700899 }
Koushik Dutta14239d22010-06-14 15:02:48 -0700900 write_fstab_root("CACHE:", file);
901 write_fstab_root("DATA:", file);
Koushik Dutta19447c02010-11-10 10:40:44 -0800902#ifdef BOARD_HAS_DATADATA
Koushik Duttaa6522b32010-06-20 13:16:06 -0700903 write_fstab_root("DATADATA:", file);
904#endif
Koushik Dutta14239d22010-06-14 15:02:48 -0700905 write_fstab_root("SYSTEM:", file);
906 write_fstab_root("SDCARD:", file);
907 write_fstab_root("SDEXT:", file);
908 fclose(file);
Koushik Dutta598cfc72010-06-20 09:42:47 -0700909}
910
911void handle_failure(int ret)
912{
913 if (ret == 0)
914 return;
915 if (0 != ensure_root_path_mounted("SDCARD:"))
916 return;
Koushik Duttaa6522b32010-06-20 13:16:06 -0700917 mkdir("/sdcard/clockworkmod", S_IRWXU);
918 __system("cp /tmp/recovery.log /sdcard/clockworkmod/recovery.log");
Koushik Dutta38e8b2b2010-08-17 22:21:53 -0700919 ui_print("/tmp/recovery.log was copied to /sdcard/clockworkmod/recovery.log. Please open ROM Manager to report the issue.\n");
Steve Kondik4123b582010-11-14 03:18:40 -0500920}