summaryrefslogtreecommitdiff
path: root/recovery/recovery_extra/recovery_amlogic.cpp (plain)
blob: 249033f6909d7be77d812dc00537208ecced041b
1#include <errno.h>
2#include <stdlib.h>
3#include <string.h>
4#include <sys/mount.h>
5#include <sys/stat.h>
6#include <sys/types.h>
7#include <sys/wait.h>
8#include <unistd.h>
9#include <ctype.h>
10#include <fcntl.h>
11#include <fs_mgr.h>
12#include "install.h"
13#include "ui.h"
14#include <dirent.h>
15#include "bootloader_message/bootloader_message.h"
16#include "recovery_amlogic.h"
17
18#include "ubootenv/set_display_mode.h"
19
20extern "C" {
21#include "ubootenv/uboot_env.h"
22}
23
24#define LOGE(...) ui_print("E:" __VA_ARGS__)
25#define LOGW(...) fprintf(stdout, "W:" __VA_ARGS__)
26#define LOGI(...) fprintf(stdout, "I:" __VA_ARGS__)
27
28static const int MAX_ARGS = 100;
29static const int MAX_ARG_LENGTH = 4096;
30#define NUM_OF_BLKDEVICE_TO_ENUM 3
31#define NUM_OF_PARTITION_TO_ENUM 6
32
33static const char *UDISK_COMMAND_FILE = "/udisk/factory_update_param.aml";
34static const char *SDCARD_COMMAND_FILE = "/sdcard/factory_update_param.aml";
35
36void setup_cache_mounts() {
37 int ret = 0;
38 ret = ensure_path_mounted("/cache");
39 if (ret != 0) {
40 format_volume("/cache");
41 }
42}
43
44
45
46static int mount_fs_rdonly(char *device_name, Volume *vol, const char *fs_type) {
47 if (!mount(device_name, vol->mount_point, fs_type,
48 MS_NOATIME | MS_NODEV | MS_NODIRATIME | MS_RDONLY, 0)) {
49 LOGW("successful to mount %s on %s by read-only\n",
50 device_name, vol->mount_point);
51 return 0;
52 } else {
53 LOGE("failed to mount %s on %s by read-only (%s)\n",
54 device_name, vol->mount_point, strerror(errno));
55 }
56
57 return -1;
58}
59
60int auto_mount_fs(char *device_name, Volume *vol) {
61 if (access(device_name, F_OK)) {
62 return -1;
63 }
64
65 if (!strcmp(vol->fs_type, "auto")) {
66 if (!mount(device_name, vol->mount_point, "vfat",
67 MS_NOATIME | MS_NODEV | MS_NODIRATIME, "")) {
68 goto auto_mounted;
69 } else {
70 if (strstr(vol->mount_point, "sdcard")) {
71 LOGW("failed to mount %s on %s (%s).try read-only ...\n",
72 device_name, vol->mount_point, strerror(errno));
73 if (!mount_fs_rdonly(device_name, vol, "vfat")) {
74 goto auto_mounted;
75 }
76 }
77 }
78
79 if (!mount(device_name, vol->mount_point, "ntfs",
80 MS_NOATIME | MS_NODEV | MS_NODIRATIME, "")) {
81 goto auto_mounted;
82 } else {
83 if (strstr(vol->mount_point, "sdcard")) {
84 LOGW("failed to mount %s on %s (%s).try read-only ...\n",
85 device_name, vol->mount_point, strerror(errno));
86 if (!mount_fs_rdonly(device_name, vol, "ntfs")) {
87 goto auto_mounted;
88 }
89 }
90 }
91
92 if (!mount(device_name, vol->mount_point, "exfat",
93 MS_NOATIME | MS_NODEV | MS_NODIRATIME, "")) {
94 goto auto_mounted;
95 } else {
96 if (strstr(vol->mount_point, "sdcard")) {
97 LOGW("failed to mount %s on %s (%s).try read-only ...\n",
98 device_name, vol->mount_point, strerror(errno));
99 if (!mount_fs_rdonly(device_name, vol, "exfat")) {
100 goto auto_mounted;
101 }
102 }
103 }
104 } else {
105 if(!mount(device_name, vol->mount_point, vol->fs_type,
106 MS_NOATIME | MS_NODEV | MS_NODIRATIME, "")) {
107 goto auto_mounted;
108 } else {
109 if (strstr(vol->mount_point, "sdcard")) {
110 LOGW("failed to mount %s on %s (%s).try read-only ...\n",
111 device_name, vol->mount_point, strerror(errno));
112 if (!mount_fs_rdonly(device_name, vol, vol->fs_type)) {
113 goto auto_mounted;
114 }
115 }
116 }
117 }
118
119 return -1;
120
121auto_mounted:
122 return 0;
123}
124
125int customize_smart_device_mounted(
126 Volume *vol) {
127 int i = 0, j = 0;
128 int first_position = 0;
129 int second_position = 0;
130 char * tmp = NULL;
131 char *mounted_device = NULL;
132 char device_name[256] = {0};
133 char device_boot[256] = {0};
134 const char *usb_device = "/dev/block/sd";
135 const char *sdcard_device = "/dev/block/mmcblk";
136
137 if (vol->blk_device != NULL) {
138 int num = 0;
139 const char *blk_device = vol->blk_device;
140 for (; *blk_device != '\0'; blk_device ++) {
141 if (*blk_device == '#') {
142 num ++;
143 }
144 }
145
146 /*
147 * Contain two '#' for blk_device name in recovery.fstab
148 * such as /dev/block/sd## (udisk)
149 * such as /dev/block/mmcblk#p# (sdcard)
150 */
151 if (num != 2) {
152 return 1; // Don't contain two '#'
153 }
154
155 if (access(vol->mount_point, F_OK)) {
156 mkdir(vol->mount_point, 0755);
157 }
158
159 // find '#' position
160 if (strchr(vol->blk_device, '#')) {
161 tmp = strchr(vol->blk_device, '#');
162 first_position = tmp - vol->blk_device;
163 if (strlen(tmp+1) > 0 && strchr(tmp+1, '#')) {
164 tmp = strchr(tmp+1, '#');
165 second_position = tmp - vol->blk_device;
166 }
167 }
168
169 if (!first_position || !second_position) {
170 LOGW("decompose blk_device error(%s) in recovery.fstab\n",
171 vol->blk_device);
172 return -1;
173 }
174
175 int copy_len = (strlen(vol->blk_device) < sizeof(device_name)) ?
176 strlen(vol->blk_device) : sizeof(device_name);
177
178 for (i = 0; i < NUM_OF_BLKDEVICE_TO_ENUM; i ++) {
179 memset(device_name, '\0', sizeof(device_name));
180 strncpy(device_name, vol->blk_device, copy_len);
181
182 if (!strncmp(device_name, sdcard_device, strlen(sdcard_device))) {
183 // start from '0' for mmcblk0p#
184 device_name[first_position] = '0' + i;
185 } else if (!strncmp(device_name, usb_device, strlen(usb_device))) {
186 // start from 'a' for sda#
187 device_name[first_position] = 'a' + i;
188 }
189
190 for (j = 1; j <= NUM_OF_PARTITION_TO_ENUM; j ++) {
191 device_name[second_position] = '0' + j;
192 if (!access(device_name, F_OK)) {
193 LOGW("try mount %s ...\n", device_name);
194 if (!auto_mount_fs(device_name, vol)) {
195 mounted_device = device_name;
196 LOGW("successful to mount %s\n", device_name);
197 goto mounted;
198 }
199 }
200 }
201
202 if (!strncmp(device_name, sdcard_device, strlen(sdcard_device))) {
203 // mmcblk0p1->mmcblk0
204 device_name[strlen(device_name) - 2] = '\0';
205 sprintf(device_boot, "%s%s", device_name, "boot0");
206 // TODO: Here,need to distinguish between cards and flash at best
207 } else if (!strncmp(device_name, usb_device, strlen(usb_device))) {
208 // sda1->sda
209 device_name[strlen(device_name) - 1] = '\0';
210 }
211
212 if (!access(device_name, F_OK)) {
213 if (strlen(device_boot) && (!access(device_boot, F_OK))) {
214 continue;
215 }
216
217 LOGW("try mount %s ...\n", device_name);
218 if (!auto_mount_fs(device_name, vol)) {
219 mounted_device = device_name;
220 LOGW("successful to mount %s\n", device_name);
221 goto mounted;
222 }
223 }
224 }
225 } else {
226 LOGE("Can't get blk_device\n");
227 }
228
229 return -1;
230
231mounted:
232 return 0;
233}
234
235int smart_device_mounted(Volume *vol) {
236 int i = 0, len = 0;
237 char * tmp = NULL;
238 char device_name[256] = {0};
239 char *mounted_device = NULL;
240
241 mkdir(vol->mount_point, 0755);
242
243 if (vol->blk_device != NULL) {
244 int ret = customize_smart_device_mounted(vol);
245 if (ret <= 0) {
246 return ret;
247 }
248 }
249
250 if (vol->blk_device != NULL) {
251 tmp = strchr(vol->blk_device, '#');
252 len = tmp - vol->blk_device;
253 if (tmp && len < 255) {
254 strncpy(device_name, vol->blk_device, len);
255 for (i = 1; i <= NUM_OF_PARTITION_TO_ENUM; i++) {
256 device_name[len] = '0' + i;
257 device_name[len + 1] = '\0';
258 LOGW("try mount %s ...\n", device_name);
259 if (!access(device_name, F_OK)) {
260 if (!auto_mount_fs(device_name, vol)) {
261 mounted_device = device_name;
262 LOGW("successful to mount %s\n", device_name);
263 goto mounted;
264 }
265 }
266 }
267
268 const char *mmcblk = "/dev/block/mmcblk";
269 if (!strncmp(device_name, mmcblk, strlen(mmcblk))) {
270 device_name[len - 1] = '\0';
271 } else {
272 device_name[len] = '\0';
273 }
274
275 LOGW("try mount %s ...\n", device_name);
276 if (!access(device_name, F_OK)) {
277 if (!auto_mount_fs(device_name, vol)) {
278 mounted_device = device_name;
279 LOGW("successful to mount %s\n", device_name);
280 goto mounted;
281 }
282 }
283 } else {
284 LOGW("try mount %s ...\n", vol->blk_device);
285 strncpy(device_name, vol->blk_device, sizeof(device_name));
286 if (!access(device_name, F_OK)) {
287 if (!auto_mount_fs(device_name, vol)) {
288 mounted_device = device_name;
289 LOGW("successful to mount %s\n", device_name);
290 goto mounted;
291 }
292 }
293 }
294 }
295
296 return -1;
297
298mounted:
299 return 0;
300}
301
302
303//return value
304// 0 mount OK
305// -1 mount Faile
306// 2 ignorel
307int ensure_path_mounted_extra(Volume *v) {
308 Volume* vUsb = volume_for_path("/udisk");
309 char tmp[128] = {0};
310
311 if (strcmp(v->fs_type, "ext4") == 0) {
312 if (strstr(v->mount_point, "system")) {
313 if (!mount(v->blk_device, v->mount_point, v->fs_type,
314 MS_NOATIME | MS_NODEV | MS_NODIRATIME | MS_RDONLY, "")) {
315 return 0;
316 }
317 } else {
318 if (!mount(v->blk_device, v->mount_point, v->fs_type,
319 MS_NOATIME | MS_NODEV | MS_NODIRATIME, "discard")) {
320 return 0;
321 }
322 }
323 LOGE("failed to mount %s (%s)\n", v->mount_point, strerror(errno));
324 return -1;
325 } else if (strcmp(v->fs_type, "vfat") == 0 ||
326 strcmp(v->fs_type, "auto") == 0 ) {
327 if (strstr(v->mount_point, "sdcard") || strstr(v->mount_point, "udisk")) {
328 int time_out = 2000000;
329 while (time_out) {
330 if (!smart_device_mounted(v)) {
331 return 0;
332 }
333 usleep(100000);
334 time_out -= 100000;
335 }
336 } else {
337 if (!mount(v->blk_device, v->mount_point, v->fs_type,
338 MS_NOATIME | MS_NODEV | MS_NODIRATIME | MS_RDONLY, "")) {
339 return 0;
340 }
341 }
342 LOGE("failed to mount %s (%s)\n", v->mount_point, strerror(errno));
343 return -1;
344 } else {
345 return 2;//not deal
346 }
347}
348
349void amlogic_init() {
350 set_display_mode("/etc/mesondisplay.cfg");
351 sleep(1);
352}
353
354void amlogic_get_args(std::vector<std::string>& args) {
355
356 if (args.size() == 1) {
357 std::string content;
358 if (ensure_path_mounted(UDISK_COMMAND_FILE) == 0 &&
359 android::base::ReadFileToString(UDISK_COMMAND_FILE, &content)) {
360
361 std::vector<std::string> tokens = android::base::Split(content, "\n");
362 for (auto it = tokens.begin(); it != tokens.end(); it++) {
363 // Skip empty and '\0'-filled tokens.
364 if (!it->empty() && (*it)[0] != '\0') {
365 args.push_back(std::move(*it));
366 }
367 }
368 LOG(INFO) << "Got " << args.size() << " arguments from " << UDISK_COMMAND_FILE;
369 }
370 }
371
372 if (args.size() == 1) {
373 std::string content;
374 if (ensure_path_mounted(SDCARD_COMMAND_FILE) == 0 &&
375 android::base::ReadFileToString(SDCARD_COMMAND_FILE, &content)) {
376
377 std::vector<std::string> tokens = android::base::Split(content, "\n");
378 for (auto it = tokens.begin(); it != tokens.end(); it++) {
379 // Skip empty and '\0'-filled tokens.
380 if (!it->empty() && (*it)[0] != '\0') {
381 args.push_back(std::move(*it));
382 }
383 }
384 LOG(INFO) << "Got " << args.size() << " arguments from " << SDCARD_COMMAND_FILE;
385 }
386 }
387
388 if (args.size() == 1) {
389 args.push_back(std::move("--show_text"));
390 }
391
392}
393