blob: 3d4734115e031b95eaf0d00a45c28bc0a6421658 [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:" },
Brint E. Kriebeld3522332010-12-11 20:52:06 -0700449#ifdef BOARD_HAS_SDCARD_INTERNAL
450 { "mount /emmc", "unmount /emmc", "SDINTERNAL:" },
451#endif
Koushik K. Dutta3f995392010-03-30 23:29:43 -0700452 { "mount /sd-ext", "unmount /sd-ext", "SDEXT:" }
Koushik K. Duttab9546a82010-03-14 22:42:30 -0700453 };
Steve Kondik4123b582010-11-14 03:18:40 -0500454
Koushik K. Dutta16f0b492010-03-19 14:37:11 -0700455 string mtds[MTD_COUNT][2] = {
Koushik K. Dutta3f995392010-03-30 23:29:43 -0700456 { "format boot", "BOOT:" },
457 { "format system", "SYSTEM:" },
458 { "format data", "DATA:" },
459 { "format cache", "CACHE:" },
460 };
Steve Kondik4123b582010-11-14 03:18:40 -0500461
Koushik K. Dutta3f995392010-03-30 23:29:43 -0700462 string mmcs[MMC_COUNT][3] = {
463 { "format sdcard", "SDCARD:" },
Brint E. Kriebeld3522332010-12-11 20:52:06 -0700464#ifdef BOARD_HAS_SDCARD_INTERNAL
465 { "format internal sdcard", "SDINTERNAL:" },
466#endif
Steve Kondik4123b582010-11-14 03:18:40 -0500467 { "format sd-ext", "SDEXT:" }
Koushik K. Dutta16f0b492010-03-19 14:37:11 -0700468 };
Steve Kondik4123b582010-11-14 03:18:40 -0500469
Koushik Duttad63eaef2010-07-14 21:01:21 -0700470 static char* confirm_format = "Confirm format?";
Koushik Duttaecd32fa2010-07-14 18:38:02 -0700471 static char* confirm = "Yes - Format";
Steve Kondik4123b582010-11-14 03:18:40 -0500472
Koushik K. Duttab9546a82010-03-14 22:42:30 -0700473 for (;;)
474 {
Koushik K. Dutta5899ac92010-03-19 13:34:36 -0700475 int ismounted[MOUNTABLE_COUNT];
Koushik K. Duttab9546a82010-03-14 22:42:30 -0700476 int i;
Koushik K. Dutta3f995392010-03-30 23:29:43 -0700477 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 -0700478 for (i = 0; i < MOUNTABLE_COUNT; i++)
Koushik K. Duttab9546a82010-03-14 22:42:30 -0700479 {
Koushik K. Dutta16f0b492010-03-19 14:37:11 -0700480 ismounted[i] = is_root_path_mounted(mounts[i][2]);
Koushik K. Duttab9546a82010-03-14 22:42:30 -0700481 options[i] = ismounted[i] ? mounts[i][1] : mounts[i][0];
482 }
Steve Kondik4123b582010-11-14 03:18:40 -0500483
Koushik K. Dutta5899ac92010-03-19 13:34:36 -0700484 for (i = 0; i < MTD_COUNT; i++)
485 {
Koushik K. Dutta16f0b492010-03-19 14:37:11 -0700486 options[MOUNTABLE_COUNT + i] = mtds[i][0];
Koushik K. Dutta5899ac92010-03-19 13:34:36 -0700487 }
Steve Kondik4123b582010-11-14 03:18:40 -0500488
Koushik K. Dutta3f995392010-03-30 23:29:43 -0700489 for (i = 0; i < MMC_COUNT; i++)
490 {
491 options[MOUNTABLE_COUNT + MTD_COUNT + i] = mmcs[i][0];
492 }
Steve Kondik4123b582010-11-14 03:18:40 -0500493
Koushik K. Dutta3f995392010-03-30 23:29:43 -0700494 options[MOUNTABLE_COUNT + MTD_COUNT + MMC_COUNT] = "mount USB storage";
495 options[MOUNTABLE_COUNT + MTD_COUNT + MMC_COUNT + 1] = NULL;
Steve Kondik4123b582010-11-14 03:18:40 -0500496
Koushik K. Duttab9546a82010-03-14 22:42:30 -0700497 int chosen_item = get_menu_selection(headers, options, 0);
498 if (chosen_item == GO_BACK)
499 break;
Koushik K. Dutta3f995392010-03-30 23:29:43 -0700500 if (chosen_item == MOUNTABLE_COUNT + MTD_COUNT + MMC_COUNT)
Koushik K. Duttab9546a82010-03-14 22:42:30 -0700501 {
502 show_mount_usb_storage_menu();
503 }
Koushik K. Dutta5899ac92010-03-19 13:34:36 -0700504 else if (chosen_item < MOUNTABLE_COUNT)
Koushik K. Duttab9546a82010-03-14 22:42:30 -0700505 {
506 if (ismounted[chosen_item])
507 {
Koushik K. Dutta16f0b492010-03-19 14:37:11 -0700508 if (0 != ensure_root_path_unmounted(mounts[chosen_item][2]))
509 ui_print("Error unmounting %s!\n", mounts[chosen_item][2]);
Koushik K. Duttab9546a82010-03-14 22:42:30 -0700510 }
511 else
512 {
Koushik K. Dutta16f0b492010-03-19 14:37:11 -0700513 if (0 != ensure_root_path_mounted(mounts[chosen_item][2]))
514 ui_print("Error mounting %s!\n", mounts[chosen_item][2]);
Koushik K. Duttab9546a82010-03-14 22:42:30 -0700515 }
516 }
Koushik K. Dutta5899ac92010-03-19 13:34:36 -0700517 else if (chosen_item < MOUNTABLE_COUNT + MTD_COUNT)
518 {
519 chosen_item = chosen_item - MOUNTABLE_COUNT;
Koushik Duttaecd32fa2010-07-14 18:38:02 -0700520 if (!confirm_selection(confirm_format, confirm))
Koushik K. Dutta16f0b492010-03-19 14:37:11 -0700521 continue;
522 ui_print("Formatting %s...\n", mtds[chosen_item][1]);
Koushik K. Dutta3f995392010-03-30 23:29:43 -0700523 if (0 != format_root_device(mtds[chosen_item][1]))
524 ui_print("Error formatting %s!\n", mtds[chosen_item][1]);
525 else
526 ui_print("Done.\n");
527 }
528 else if (chosen_item < MOUNTABLE_COUNT + MTD_COUNT + MMC_COUNT)
529 {
530 chosen_item = chosen_item - MOUNTABLE_COUNT - MTD_COUNT;
Koushik Duttaecd32fa2010-07-14 18:38:02 -0700531 if (!confirm_selection(confirm_format, confirm))
Koushik K. Dutta3f995392010-03-30 23:29:43 -0700532 continue;
533 ui_print("Formatting %s...\n", mmcs[chosen_item][1]);
Koushik Dutta19447c02010-11-10 10:40:44 -0800534 if (0 != format_unknown_device(mmcs[chosen_item][1]))
Koushik K. Dutta3f995392010-03-30 23:29:43 -0700535 ui_print("Error formatting %s!\n", mmcs[chosen_item][1]);
536 else
537 ui_print("Done.\n");
Koushik K. Dutta5899ac92010-03-19 13:34:36 -0700538 }
Koushik K. Duttab9546a82010-03-14 22:42:30 -0700539 }
540}
541
Koushik K. Dutta72a1db62010-03-07 14:10:26 -0800542#define EXTENDEDCOMMAND_SCRIPT "/cache/recovery/extendedcommand"
543
544int extendedcommand_file_exists()
Koushik K. Duttaf68aaaf2010-03-07 13:39:21 -0800545{
Koushik K. Duttaf68aaaf2010-03-07 13:39:21 -0800546 struct stat file_info;
Koushik K. Dutta72a1db62010-03-07 14:10:26 -0800547 return 0 == stat(EXTENDEDCOMMAND_SCRIPT, &file_info);
548}
549
Koushik K. Dutta3836f722010-03-11 22:17:43 -0800550int run_script_from_buffer(char* script_data, int script_len, char* filename)
Koushik K. Dutta72a1db62010-03-07 14:10:26 -0800551{
Koushik K. Duttaf68aaaf2010-03-07 13:39:21 -0800552 /* Parse the script. Note that the script and parse tree are never freed.
553 */
554 const AmCommandList *commands = parseAmendScript(script_data, script_len);
555 if (commands == NULL) {
556 printf("Syntax error in update script\n");
557 return 1;
558 } else {
Koushik K. Dutta72a1db62010-03-07 14:10:26 -0800559 printf("Parsed %.*s\n", script_len, filename);
Koushik K. Duttaf68aaaf2010-03-07 13:39:21 -0800560 }
561
562 /* Execute the script.
563 */
564 int ret = execCommandList((ExecContext *)1, commands);
565 if (ret != 0) {
566 int num = ret;
Koushik K. Duttaee57bbc2010-03-12 23:21:12 -0800567 char *line = NULL, *next = script_data;
Koushik K. Duttaf68aaaf2010-03-07 13:39:21 -0800568 while (next != NULL && ret-- > 0) {
569 line = next;
570 next = memchr(line, '\n', script_data + script_len - line);
571 if (next != NULL) *next++ = '\0';
572 }
573 printf("Failure at line %d:\n%s\n", num, next ? line : "(not found)");
574 return 1;
Steve Kondik4123b582010-11-14 03:18:40 -0500575 }
576
Koushik K. Duttaf68aaaf2010-03-07 13:39:21 -0800577 return 0;
578}
Koushik K. Dutta72a1db62010-03-07 14:10:26 -0800579
Koushik K. Dutta6771aca2010-04-03 23:28:39 -0700580int run_script(char* filename)
Koushik K. Dutta3836f722010-03-11 22:17:43 -0800581{
582 struct stat file_info;
583 if (0 != stat(filename, &file_info)) {
584 printf("Error executing stat on file: %s\n", filename);
585 return 1;
586 }
Steve Kondik4123b582010-11-14 03:18:40 -0500587
Koushik K. Dutta3836f722010-03-11 22:17:43 -0800588 int script_len = file_info.st_size;
Koushik K. Dutta707fa6d2010-03-23 11:44:33 -0700589 char* script_data = (char*)malloc(script_len + 1);
Koushik K. Dutta3836f722010-03-11 22:17:43 -0800590 FILE *file = fopen(filename, "rb");
591 fread(script_data, script_len, 1, file);
Koushik K. Dutta707fa6d2010-03-23 11:44:33 -0700592 // supposedly not necessary, but let's be safe.
593 script_data[script_len] = '\0';
Koushik K. Dutta3836f722010-03-11 22:17:43 -0800594 fclose(file);
Koushik Duttae25908b2010-06-21 08:16:19 -0700595 LOGI("Running script:\n");
596 LOGI("\n%s\n", script_data);
Koushik K. Dutta3836f722010-03-11 22:17:43 -0800597
Koushik K. Duttaf3534d02010-04-18 18:06:24 -0700598 int ret = run_script_from_buffer(script_data, script_len, filename);
Koushik K. Dutta1d53c4e2010-04-02 16:46:21 -0700599 free(script_data);
600 return ret;
Koushik K. Dutta3836f722010-03-11 22:17:43 -0800601}
602
Koushik K. Dutta72a1db62010-03-07 14:10:26 -0800603int run_and_remove_extendedcommand()
604{
Koushik K. Dutta6771aca2010-04-03 23:28:39 -0700605 char tmp[PATH_MAX];
606 sprintf(tmp, "cp %s /tmp/%s", EXTENDEDCOMMAND_SCRIPT, basename(EXTENDEDCOMMAND_SCRIPT));
607 __system(tmp);
608 remove(EXTENDEDCOMMAND_SCRIPT);
Koushik K. Dutta3a25cf52010-03-08 19:22:41 -0800609 int i = 0;
610 for (i = 20; i > 0; i--) {
611 ui_print("Waiting for SD Card to mount (%ds)\n", i);
612 if (ensure_root_path_mounted("SDCARD:") == 0) {
613 ui_print("SD Card mounted...\n");
614 break;
615 }
616 sleep(1);
617 }
Koushik Dutta92077c12010-07-15 00:10:08 -0700618 remove("/sdcard/clockworkmod/.recoverycheckpoint");
Koushik K. Dutta3a25cf52010-03-08 19:22:41 -0800619 if (i == 0) {
620 ui_print("Timed out waiting for SD card... continuing anyways.");
621 }
Steve Kondik4123b582010-11-14 03:18:40 -0500622
Koushik K. Dutta6771aca2010-04-03 23:28:39 -0700623 sprintf(tmp, "/tmp/%s", basename(EXTENDEDCOMMAND_SCRIPT));
624 return run_script(tmp);
Koushik K. Dutta72a1db62010-03-07 14:10:26 -0800625}
626
627int amend_main(int argc, char** argv)
628{
Steve Kondik4123b582010-11-14 03:18:40 -0500629 if (argc != 2)
Koushik K. Dutta72a1db62010-03-07 14:10:26 -0800630 {
631 printf("Usage: amend <script>\n");
632 return 0;
633 }
634
635 RecoveryCommandContext ctx = { NULL };
636 if (register_update_commands(&ctx)) {
637 LOGE("Can't install update commands\n");
638 }
Koushik K. Dutta6771aca2010-04-03 23:28:39 -0700639 return run_script(argv[1]);
Koushik K. Dutta5306db52010-03-08 14:09:35 -0800640}
Koushik K. Dutta5899ac92010-03-19 13:34:36 -0700641
Koushik K. Duttafe84a7f2010-03-25 18:19:23 -0700642void show_nandroid_advanced_restore_menu()
643{
644 if (ensure_root_path_mounted("SDCARD:") != 0) {
645 LOGE ("Can't mount /sdcard\n");
646 return;
647 }
648
649 static char* advancedheaders[] = { "Choose an image to restore",
650 "",
651 "Choose an image to restore",
652 "first. The next menu will",
653 "you more options.",
654 "",
655 NULL
656 };
657
658 char* file = choose_file_menu("/sdcard/clockworkmod/backup/", NULL, advancedheaders);
659 if (file == NULL)
660 return;
661
662 static char* headers[] = { "Nandroid Advanced Restore",
663 "",
664 NULL
665 };
666
667 static char* list[] = { "Restore boot",
668 "Restore system",
669 "Restore data",
670 "Restore cache",
Koushik K. Dutta68b01902010-04-01 12:20:39 -0700671 "Restore sd-ext",
Koushik K. Duttafe84a7f2010-03-25 18:19:23 -0700672 NULL
673 };
674
Koushik Duttad63eaef2010-07-14 21:01:21 -0700675
676 static char* confirm_restore = "Confirm restore?";
677
Koushik K. Duttafe84a7f2010-03-25 18:19:23 -0700678 int chosen_item = get_menu_selection(headers, list, 0);
679 switch (chosen_item)
680 {
681 case 0:
Koushik Duttad63eaef2010-07-14 21:01:21 -0700682 if (confirm_selection(confirm_restore, "Yes - Restore boot"))
683 nandroid_restore(file, 1, 0, 0, 0, 0);
Koushik K. Duttafe84a7f2010-03-25 18:19:23 -0700684 break;
685 case 1:
Koushik Duttad63eaef2010-07-14 21:01:21 -0700686 if (confirm_selection(confirm_restore, "Yes - Restore system"))
687 nandroid_restore(file, 0, 1, 0, 0, 0);
Koushik K. Duttafe84a7f2010-03-25 18:19:23 -0700688 break;
689 case 2:
Koushik Duttad63eaef2010-07-14 21:01:21 -0700690 if (confirm_selection(confirm_restore, "Yes - Restore data"))
691 nandroid_restore(file, 0, 0, 1, 0, 0);
Koushik K. Duttafe84a7f2010-03-25 18:19:23 -0700692 break;
693 case 3:
Koushik Duttad63eaef2010-07-14 21:01:21 -0700694 if (confirm_selection(confirm_restore, "Yes - Restore cache"))
695 nandroid_restore(file, 0, 0, 0, 1, 0);
Koushik K. Duttafe84a7f2010-03-25 18:19:23 -0700696 break;
Koushik Dutta2f73e582010-04-18 16:00:21 -0700697 case 4:
Koushik Duttad63eaef2010-07-14 21:01:21 -0700698 if (confirm_selection(confirm_restore, "Yes - Restore sd-ext"))
699 nandroid_restore(file, 0, 0, 0, 0, 1);
Koushik Dutta2f73e582010-04-18 16:00:21 -0700700 break;
Koushik K. Duttafe84a7f2010-03-25 18:19:23 -0700701 }
702}
703
Koushik K. Dutta5899ac92010-03-19 13:34:36 -0700704void show_nandroid_menu()
705{
706 static char* headers[] = { "Nandroid",
707 "",
Steve Kondik4123b582010-11-14 03:18:40 -0500708 NULL
Koushik K. Dutta5899ac92010-03-19 13:34:36 -0700709 };
710
Steve Kondik4123b582010-11-14 03:18:40 -0500711 static char* list[] = { "Backup",
Koushik K. Dutta5899ac92010-03-19 13:34:36 -0700712 "Restore",
Koushik K. Duttafe84a7f2010-03-25 18:19:23 -0700713 "Advanced Restore",
Koushik K. Dutta5899ac92010-03-19 13:34:36 -0700714 NULL
715 };
716
717 int chosen_item = get_menu_selection(headers, list, 0);
718 switch (chosen_item)
719 {
720 case 0:
721 {
Koushik K. Dutta5899ac92010-03-19 13:34:36 -0700722 char backup_path[PATH_MAX];
Koushik K. Dutta6a26e7c2010-03-27 15:26:11 -0700723 time_t t = time(NULL);
724 struct tm *tmp = localtime(&t);
725 if (tmp == NULL)
726 {
727 struct timeval tp;
728 gettimeofday(&tp, NULL);
729 sprintf(backup_path, "/sdcard/clockworkmod/backup/%d", tp.tv_sec);
730 }
731 else
732 {
733 strftime(backup_path, sizeof(backup_path), "/sdcard/clockworkmod/backup/%F.%H.%M.%S", tmp);
734 }
Koushik K. Dutta5899ac92010-03-19 13:34:36 -0700735 nandroid_backup(backup_path);
736 }
737 break;
738 case 1:
739 show_nandroid_restore_menu();
740 break;
Koushik K. Duttafe84a7f2010-03-25 18:19:23 -0700741 case 2:
742 show_nandroid_advanced_restore_menu();
743 break;
Koushik K. Dutta5899ac92010-03-19 13:34:36 -0700744 }
Koushik K. Duttaa496b512010-03-19 14:51:45 -0700745}
746
Koushik Duttafd1579b2010-05-01 12:46:55 -0700747void wipe_battery_stats()
748{
749 ensure_root_path_mounted("DATA:");
750 remove("/data/system/batterystats.bin");
751 ensure_root_path_unmounted("DATA:");
752}
753
Koushik K. Duttaa496b512010-03-19 14:51:45 -0700754void show_advanced_menu()
755{
756 static char* headers[] = { "Advanced and Debugging Menu",
757 "",
758 NULL
759 };
760
Koushik K. Dutta7fe4d7b2010-04-06 23:04:52 -0700761 static char* list[] = { "Reboot Recovery",
Koushik Dutta49af23c2010-06-21 13:45:51 -0700762 "Wipe Dalvik Cache",
Koushik Duttafd1579b2010-05-01 12:46:55 -0700763 "Wipe Battery Stats",
Koushik Dutta598cfc72010-06-20 09:42:47 -0700764 "Report Error",
Koushik K. Dutta7fe4d7b2010-04-06 23:04:52 -0700765 "Key Test",
Koushik Duttae17a78d2010-08-29 12:35:10 -0700766#ifndef BOARD_HAS_SMALL_RECOVERY
Koushik Duttaceddcd52010-08-23 16:13:14 -0700767 "Partition SD Card",
768 "Fix Permissions",
Brint E. Kriebeld3522332010-12-11 20:52:06 -0700769#ifdef BOARD_HAS_SDCARD_INTERNAL
770 "Partition Internal SD Card",
771#endif
Koushik Duttae17a78d2010-08-29 12:35:10 -0700772#endif
Koushik K. Duttaa496b512010-03-19 14:51:45 -0700773 NULL
774 };
775
776 for (;;)
777 {
778 int chosen_item = get_menu_selection(headers, list, 0);
779 if (chosen_item == GO_BACK)
780 break;
781 switch (chosen_item)
782 {
783 case 0:
Koushik K. Dutta7fe4d7b2010-04-06 23:04:52 -0700784 __reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, LINUX_REBOOT_CMD_RESTART2, "recovery");
785 break;
786 case 1:
Koushik Duttad63eaef2010-07-14 21:01:21 -0700787 {
Koushik Dutta49af23c2010-06-21 13:45:51 -0700788 if (0 != ensure_root_path_mounted("DATA:"))
789 break;
Koushik Dutta6c7745d2010-08-07 12:17:13 -0700790 ensure_root_path_mounted("SDEXT:");
791 ensure_root_path_mounted("CACHE:");
792 if (confirm_selection( "Confirm wipe?", "Yes - Wipe Dalvik Cache")) {
Koushik Duttad63eaef2010-07-14 21:01:21 -0700793 __system("rm -r /data/dalvik-cache");
Koushik Dutta6c7745d2010-08-07 12:17:13 -0700794 __system("rm -r /cache/dalvik-cache");
795 __system("rm -r /sd-ext/dalvik-cache");
796 }
Koushik Dutta49af23c2010-06-21 13:45:51 -0700797 ensure_root_path_unmounted("DATA:");
Koushik Dutta6c7745d2010-08-07 12:17:13 -0700798 ui_print("Dalvik Cache wiped.\n");
Koushik Duttafd1579b2010-05-01 12:46:55 -0700799 break;
Koushik Duttad63eaef2010-07-14 21:01:21 -0700800 }
Koushik Duttafd1579b2010-05-01 12:46:55 -0700801 case 2:
Koushik Duttad63eaef2010-07-14 21:01:21 -0700802 {
803 if (confirm_selection( "Confirm wipe?", "Yes - Wipe Battery Stats"))
804 wipe_battery_stats();
Koushik Dutta598cfc72010-06-20 09:42:47 -0700805 break;
Koushik Duttad63eaef2010-07-14 21:01:21 -0700806 }
Koushik Dutta598cfc72010-06-20 09:42:47 -0700807 case 3:
Koushik Dutta49af23c2010-06-21 13:45:51 -0700808 handle_failure(1);
809 break;
810 case 4:
Koushik K. Duttaa496b512010-03-19 14:51:45 -0700811 {
812 ui_print("Outputting key codes.\n");
813 ui_print("Go back to end debugging.\n");
814 int key;
815 int action;
816 do
817 {
818 key = ui_wait_key();
819 action = device_handle_key(key, 1);
820 ui_print("Key: %d\n", key);
821 }
822 while (action != GO_BACK);
Koushik Dutta56606a22010-08-23 16:15:33 -0700823 break;
Koushik K. Duttaa496b512010-03-19 14:51:45 -0700824 }
Koushik Duttaf0e31b82010-08-17 16:55:38 -0700825 case 5:
826 {
Koushik Duttaceddcd52010-08-23 16:13:14 -0700827 static char* ext_sizes[] = { "128M",
828 "256M",
829 "512M",
830 "1024M",
Brint E. Kriebel0b233312010-11-14 15:31:17 -0700831 "2048M",
832 "4096M",
Koushik Duttaceddcd52010-08-23 16:13:14 -0700833 NULL };
834
835 static char* swap_sizes[] = { "0M",
836 "32M",
837 "64M",
838 "128M",
839 "256M",
840 NULL };
841
842 static char* ext_headers[] = { "Ext Size", "", NULL };
843 static char* swap_headers[] = { "Swap Size", "", NULL };
844
845 int ext_size = get_menu_selection(ext_headers, ext_sizes, 0);
846 if (ext_size == GO_BACK)
847 continue;
Steve Kondik4123b582010-11-14 03:18:40 -0500848
Koushik Duttaceddcd52010-08-23 16:13:14 -0700849 int swap_size = get_menu_selection(swap_headers, swap_sizes, 0);
850 if (swap_size == GO_BACK)
851 continue;
852
853 char sddevice[256];
854 const RootInfo *ri = get_root_info_for_path("SDCARD:");
855 strcpy(sddevice, ri->device);
856 // we only want the mmcblk, not the partition
857 sddevice[strlen("/dev/block/mmcblkX")] = NULL;
858 char cmd[PATH_MAX];
859 setenv("SDPATH", sddevice, 1);
860 sprintf(cmd, "sdparted -es %s -ss %s -efs ext3 -s", ext_sizes[ext_size], swap_sizes[swap_size]);
861 ui_print("Partitioning SD Card... please wait...\n");
862 if (0 == __system(cmd))
863 ui_print("Done!\n");
864 else
865 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 -0700866 break;
Koushik Duttaf0e31b82010-08-17 16:55:38 -0700867 }
Koushik Dutta38e8b2b2010-08-17 22:21:53 -0700868 case 6:
869 {
Koushik Duttaceddcd52010-08-23 16:13:14 -0700870 ensure_root_path_mounted("SYSTEM:");
871 ensure_root_path_mounted("DATA:");
872 ui_print("Fixing permissions...\n");
873 __system("fix_permissions");
874 ui_print("Done!\n");
Koushik Dutta56606a22010-08-23 16:15:33 -0700875 break;
Koushik Dutta38e8b2b2010-08-17 22:21:53 -0700876 }
Brint E. Kriebeld3522332010-12-11 20:52:06 -0700877 case 7:
878 {
879 static char* ext_sizes[] = { "128M",
880 "256M",
881 "512M",
882 "1024M",
883 "2048M",
884 "4096M",
885 NULL };
886
887 static char* swap_sizes[] = { "0M",
888 "32M",
889 "64M",
890 "128M",
891 "256M",
892 NULL };
893
894 static char* ext_headers[] = { "Data Size", "", NULL };
895 static char* swap_headers[] = { "Swap Size", "", NULL };
896
897 int ext_size = get_menu_selection(ext_headers, ext_sizes, 0);
898 if (ext_size == GO_BACK)
899 continue;
900
901 int swap_size = 0;
902 if (swap_size == GO_BACK)
903 continue;
904
905 char sddevice[256];
906 const RootInfo *ri = get_root_info_for_path("SDINTERNAL:");
907 strcpy(sddevice, ri->device);
908 // we only want the mmcblk, not the partition
909 sddevice[strlen("/dev/block/mmcblkX")] = NULL;
910 char cmd[PATH_MAX];
911 setenv("SDPATH", sddevice, 1);
912 sprintf(cmd, "sdparted -es %s -ss %s -efs ext3 -s", ext_sizes[ext_size], swap_sizes[swap_size]);
913 ui_print("Partitioning Internal SD Card... please wait...\n");
914 if (0 == __system(cmd))
915 ui_print("Done!\n");
916 else
917 ui_print("An error occured while partitioning your Internal SD Card. Please see /tmp/recovery.log for more details.\n");
918 break;
919 }
Koushik K. Duttaa496b512010-03-19 14:51:45 -0700920 }
921 }
Koushik Dutta14239d22010-06-14 15:02:48 -0700922}
923
924void write_fstab_root(char *root_path, FILE *file)
925{
926 RootInfo *info = get_root_info_for_path(root_path);
Koushik Duttaa6522b32010-06-20 13:16:06 -0700927 if (info == NULL) {
928 LOGW("Unable to get root info for %s during fstab generation!", root_path);
Koushik Dutta598cfc72010-06-20 09:42:47 -0700929 return;
Koushik Duttaa6522b32010-06-20 13:16:06 -0700930 }
Koushik Dutta19447c02010-11-10 10:40:44 -0800931 char device[PATH_MAX];
932 int ret = get_root_partition_device(root_path, device);
933 if (ret == 0)
Koushik Dutta14239d22010-06-14 15:02:48 -0700934 {
Koushik Dutta19447c02010-11-10 10:40:44 -0800935 fprintf(file, "%s ", device);
Koushik Dutta14239d22010-06-14 15:02:48 -0700936 }
937 else
938 {
Koushik Dutta19447c02010-11-10 10:40:44 -0800939 fprintf(file, "%s ", info->device);
Koushik Dutta14239d22010-06-14 15:02:48 -0700940 }
Steve Kondik4123b582010-11-14 03:18:40 -0500941
Koushik Dutta14239d22010-06-14 15:02:48 -0700942 fprintf(file, "%s ", info->mount_point);
Steve Kondik4123b582010-11-14 03:18:40 -0500943 fprintf(file, "%s %s\n", info->filesystem, info->filesystem_options == NULL ? "rw" : info->filesystem_options);
Koushik Dutta14239d22010-06-14 15:02:48 -0700944}
945
946void create_fstab()
947{
Koushik Duttacd44ab92010-06-23 00:02:14 -0700948 __system("touch /etc/mtab");
Koushik Dutta14239d22010-06-14 15:02:48 -0700949 FILE *file = fopen("/etc/fstab", "w");
Koushik Duttaa6522b32010-06-20 13:16:06 -0700950 if (file == NULL) {
951 LOGW("Unable to create /etc/fstab!");
Koushik Dutta598cfc72010-06-20 09:42:47 -0700952 return;
Koushik Duttaa6522b32010-06-20 13:16:06 -0700953 }
Koushik Dutta14239d22010-06-14 15:02:48 -0700954 write_fstab_root("CACHE:", file);
955 write_fstab_root("DATA:", file);
Koushik Dutta19447c02010-11-10 10:40:44 -0800956#ifdef BOARD_HAS_DATADATA
Koushik Duttaa6522b32010-06-20 13:16:06 -0700957 write_fstab_root("DATADATA:", file);
958#endif
Koushik Dutta14239d22010-06-14 15:02:48 -0700959 write_fstab_root("SYSTEM:", file);
960 write_fstab_root("SDCARD:", file);
961 write_fstab_root("SDEXT:", file);
962 fclose(file);
Koushik Dutta598cfc72010-06-20 09:42:47 -0700963}
964
965void handle_failure(int ret)
966{
967 if (ret == 0)
968 return;
969 if (0 != ensure_root_path_mounted("SDCARD:"))
970 return;
Koushik Duttaa6522b32010-06-20 13:16:06 -0700971 mkdir("/sdcard/clockworkmod", S_IRWXU);
972 __system("cp /tmp/recovery.log /sdcard/clockworkmod/recovery.log");
Koushik Dutta38e8b2b2010-08-17 22:21:53 -0700973 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 -0500974}