Browse Source

sr: Get a proper shell environment in recovery

 * ADB support
 * Toybox applets
 * mksh
 * Set time

Change-Id: I80b0e2aa5eb7142eaa9f157709f4e029077d8dfa
Steve Kondik 7 years ago
parent
commit
b03e33f71f
6 changed files with 297 additions and 6 deletions
  1. 34
    0
      Android.mk
  2. 3
    0
      common.h
  3. 7
    3
      etc/init.rc
  4. 70
    0
      etc/mkshrc
  5. 149
    3
      recovery.cpp
  6. 34
    0
      recovery_cmds.h

+ 34
- 0
Android.mk View File

@@ -1,4 +1,6 @@
1 1
 # Copyright (C) 2007 The Android Open Source Project
2
+# Copyright (C) 2015 The CyanogenMod Project
3
+# Copyright (C) 2017 The Lineage Android Project
2 4
 #
3 5
 # Licensed under the Apache License, Version 2.0 (the "License");
4 6
 # you may not use this file except in compliance with the License.
@@ -159,12 +161,14 @@ LOCAL_STATIC_LIBRARIES := \
159 161
     libbatterymonitor
160 162
 
161 163
 LOCAL_STATIC_LIBRARIES += \
164
+    libmksh_driver \
162 165
     librecovery \
163 166
     libverifier \
164 167
     libbootloader_message \
165 168
     libfs_mgr \
166 169
     libext4_utils \
167 170
     libsparse \
171
+    libreboot \
168 172
     libziparchive \
169 173
     libotautil \
170 174
     libmounts \
@@ -204,8 +208,38 @@ ifeq ($(BOARD_CACHEIMAGE_PARTITION_SIZE),)
204 208
 LOCAL_REQUIRED_MODULES += recovery-persist recovery-refresh
205 209
 endif
206 210
 
211
+LOCAL_REQUIRED_MODULES += \
212
+    toybox_static \
213
+    recovery_mkshrc
214
+
215
+# Symlinks
216
+RECOVERY_TOOLS := \
217
+    reboot \
218
+    setup_adbd \
219
+    sh
220
+LOCAL_POST_INSTALL_CMD := $(hide) $(foreach t,$(RECOVERY_TOOLS),ln -sf ${LOCAL_MODULE} $(LOCAL_MODULE_PATH)/$(t);)
221
+
207 222
 include $(BUILD_EXECUTABLE)
208 223
 
224
+# mkshrc
225
+include $(CLEAR_VARS)
226
+LOCAL_MODULE := recovery_mkshrc
227
+LOCAL_MODULE_TAGS := optional
228
+LOCAL_MODULE_CLASS := ETC
229
+LOCAL_MODULE_PATH := $(TARGET_RECOVERY_ROOT_OUT)/etc
230
+LOCAL_SRC_FILES := etc/mkshrc
231
+LOCAL_MODULE_STEM := mkshrc
232
+include $(BUILD_PREBUILT)
233
+
234
+# Reboot static library
235
+include $(CLEAR_VARS)
236
+LOCAL_MODULE := libreboot
237
+LOCAL_MODULE_TAGS := optional
238
+LOCAL_CFLAGS := -Dmain=reboot_main
239
+LOCAL_SRC_FILES := ../../system/core/reboot/reboot.c
240
+include $(BUILD_STATIC_LIBRARY)
241
+
242
+
209 243
 # recovery-persist (system partition dynamic executable run after /data mounts)
210 244
 # ===============================
211 245
 include $(CLEAR_VARS)

+ 3
- 0
common.h View File

@@ -26,6 +26,9 @@
26 26
 // device-specific recovery libraries. We static assert the value consistency in recovery.cpp.
27 27
 static constexpr int kRecoveryApiVersion = 3;
28 28
 
29
+// Minimum valid seconds since epoch (2017-01-01 00:00:00)
30
+#define TV_MIN 1483228800
31
+
29 32
 class RecoveryUI;
30 33
 
31 34
 extern RecoveryUI* ui;

+ 7
- 3
etc/init.rc View File

@@ -87,15 +87,19 @@ service charger /charger -r
87 87
 service recovery /sbin/recovery
88 88
     seclabel u:r:recovery:s0
89 89
 
90
+service setup_adbd /sbin/setup_adbd
91
+    oneshot
92
+    seclabel u:r:recovery:s0
93
+    disabled
94
+
90 95
 service adbd /sbin/adbd --root_seclabel=u:r:su:s0 --device_banner=recovery
91 96
     disabled
92 97
     socket adbd stream 660 system system
93 98
     seclabel u:r:adbd:s0
94 99
 
95
-# Always start adbd on userdebug and eng builds
100
+# setup_adbd will start adb once it has checked the keys
96 101
 on property:ro.debuggable=1
97
-    write /sys/class/android_usb/android0/enable 1
98
-    start adbd
102
+    start setup_adbd
99 103
 
100 104
 # Restart adbd so it can run as root
101 105
 on property:lineage.service.adb.root=1

+ 70
- 0
etc/mkshrc View File

@@ -0,0 +1,70 @@
1
+# Copyright (c) 2010, 2012, 2013, 2014
2
+#	Thorsten Glaser <tg@mirbsd.org>
3
+# This file is provided under the same terms as mksh.
4
+#-
5
+# Minimal /system/etc/mkshrc for Android
6
+#
7
+# Support: https://launchpad.net/mksh
8
+
9
+: ${HOME:=/}
10
+: ${HOSTNAME:=$(getprop ro.product.device)}
11
+: ${HOSTNAME:=android}
12
+: ${MKSH:=/sbin/sh}
13
+: ${SHELL:=$MKSH}
14
+: ${TERM:=linux}
15
+: ${TMPDIR:=/tmp}
16
+: ${USER:=$(id -un)}
17
+export HOME HOSTNAME MKSH SHELL TERM TMPDIR USER
18
+
19
+if (( USER_ID )); then PS1='$'; else PS1='#'; fi
20
+PS4='[$EPOCHREALTIME] '; PS1='${|
21
+	local e=$?
22
+
23
+	(( e )) && REPLY+="$e|"
24
+
25
+	return $e
26
+}$USER@$HOSTNAME:${PWD:-?} '"$PS1 "
27
+
28
+function hd {
29
+	local -Uui16 -Z11 pos=0
30
+	local -Uui16 -Z5 hv=2147483647
31
+	local dasc line i
32
+
33
+	cat "$@" | { set +U; if read -arN -1 line; then
34
+		typeset -i1 'line[*]'
35
+		i=0
36
+		while (( i < ${#line[*]} )); do
37
+			hv=${line[i++]}
38
+			if (( (pos & 15) == 0 )); then
39
+				(( pos )) && print -r -- "$dasc|"
40
+				print -n "${pos#16#}  "
41
+				dasc=' |'
42
+			fi
43
+			print -n "${hv#16#} "
44
+			if (( (hv < 32) || (hv > 126) )); then
45
+				dasc+=.
46
+			else
47
+				dasc+=${line[i-1]#1#}
48
+			fi
49
+			(( (pos++ & 15) == 7 )) && print -n -- '- '
50
+		done
51
+		while (( pos & 15 )); do
52
+			print -n '   '
53
+			(( (pos++ & 15) == 7 )) && print -n -- '- '
54
+		done
55
+		(( hv == 2147483647 )) || print -r -- "$dasc|"
56
+	fi; }
57
+}
58
+
59
+function setenv {
60
+	eval export "\"$1\""'="$2"'
61
+}
62
+
63
+for p in ~/bin; do
64
+	[[ -d $p/. ]] || continue
65
+	[[ :$PATH: = *:$p:* ]] || PATH=$p:$PATH
66
+done
67
+
68
+unset p
69
+
70
+: place customisations above this line

+ 149
- 3
recovery.cpp View File

@@ -73,6 +73,32 @@
73 73
 #include "stub_ui.h"
74 74
 #include "ui.h"
75 75
 
76
+#include "recovery_cmds.h"
77
+
78
+struct recovery_cmd {
79
+  const char *name;
80
+  int (*main_func)(int argc, char **argv);
81
+};
82
+
83
+static const struct recovery_cmd recovery_cmds[] = {
84
+  { "reboot",         reboot_main },
85
+  { "poweroff",       reboot_main },
86
+  { "sh",             mksh_main },
87
+  { nullptr, nullptr },
88
+};
89
+
90
+struct recovery_cmd get_command(char* command) {
91
+  int i;
92
+
93
+  for (i = 0; recovery_cmds[i].name; i++) {
94
+    if (strcmp(command, recovery_cmds[i].name) == 0) {
95
+      break;
96
+    }
97
+  }
98
+
99
+  return recovery_cmds[i];
100
+}
101
+
76 102
 static const struct option OPTIONS[] = {
77 103
   { "update_package", required_argument, NULL, 'u' },
78 104
   { "retry_count", required_argument, NULL, 'n' },
@@ -132,6 +158,12 @@ static_assert(kRecoveryApiVersion == RECOVERY_API_VERSION, "Mismatching recovery
132 158
 static std::string locale;
133 159
 static bool has_cache = false;
134 160
 
161
+static const char* adb_keys_data = "/data/misc/adb/adb_keys";
162
+static const char* adb_keys_root = "/adb_keys";
163
+static const char* time_off_1_data = "/data/time/ats_1";
164
+static const char* time_off_2_data = "/data/system/time/ats_1";
165
+static const char* time_off_root = "/ats";
166
+
135 167
 RecoveryUI* ui = nullptr;
136 168
 bool modified_flash = false;
137 169
 std::string stage;
@@ -210,6 +242,38 @@ static void check_and_fclose(FILE *fp, const char *name) {
210 242
     fclose(fp);
211 243
 }
212 244
 
245
+static bool file_copy(const char* src, const char* dst) {
246
+  bool ret = false;
247
+  char tmpdst[PATH_MAX];
248
+  FILE* sfp;
249
+  FILE* dfp;
250
+
251
+  snprintf(tmpdst, sizeof(tmpdst), "%s.tmp", dst);
252
+  sfp = fopen(src, "r");
253
+  dfp = fopen(tmpdst, "w");
254
+  if (sfp && dfp) {
255
+    char buf[4096];
256
+    size_t nr, nw;
257
+    while ((nr = fread(buf, 1, sizeof(buf), sfp)) != 0) {
258
+      nw = fwrite(buf, 1, nr, dfp);
259
+      if (nr != nw)
260
+        break;
261
+    }
262
+    ret = (!ferror(sfp) && !ferror(dfp));
263
+  }
264
+  if (dfp) fclose(dfp);
265
+  if (sfp) fclose(sfp);
266
+
267
+  if (ret) {
268
+    ret = (rename(tmpdst, dst) == 0);
269
+  }
270
+  else {
271
+    unlink(tmpdst);
272
+  }
273
+
274
+  return ret;
275
+}
276
+
213 277
 bool is_ro_debuggable() {
214 278
     return android::base::GetBoolProperty("ro.debuggable", false);
215 279
 }
@@ -1333,6 +1397,59 @@ static void log_failure_code(ErrorCode code, const char *update_package) {
1333 1397
     LOG(INFO) << log_content;
1334 1398
 }
1335 1399
 
1400
+static void copy_userdata_files() {
1401
+  if (ensure_path_mounted("/data") == 0) {
1402
+    if (access(adb_keys_root, F_OK) != 0) {
1403
+      if (access(adb_keys_data, R_OK) == 0) {
1404
+        file_copy(adb_keys_data, adb_keys_root);
1405
+      }
1406
+    }
1407
+    if (access(time_off_root, F_OK) != 0) {
1408
+      if (access(time_off_1_data, R_OK) == 0) {
1409
+        file_copy(time_off_1_data, time_off_root);
1410
+      }
1411
+      else if (access(time_off_2_data, R_OK) == 0) {
1412
+        file_copy(time_off_2_data, time_off_root);
1413
+      }
1414
+    }
1415
+    ensure_path_unmounted("/data");
1416
+  }
1417
+}
1418
+
1419
+static void set_time() {
1420
+  struct timeval now;
1421
+  FILE* fp;
1422
+
1423
+  gettimeofday(&now, nullptr);
1424
+  if (now.tv_sec <= TV_MIN) {
1425
+    fp = fopen(time_off_root, "r");
1426
+    if (fp) {
1427
+      uint64_t off;
1428
+      if (fread(&off, 1, sizeof(off), fp) == sizeof(off)) {
1429
+        now.tv_sec = off / 1000;
1430
+        now.tv_usec = (off % 1000) * 1000;
1431
+        if (now.tv_sec > TV_MIN) {
1432
+          settimeofday(&now, nullptr);
1433
+        }
1434
+      }
1435
+      fclose(fp);
1436
+    }
1437
+  }
1438
+}
1439
+
1440
+static void setup_adbd() {
1441
+  int tries;
1442
+  for (tries = 0; tries < 5; ++tries) {
1443
+    if (access(adb_keys_root, F_OK) == 0) {
1444
+      break;
1445
+    }
1446
+    sleep(1);
1447
+  }
1448
+
1449
+  // Trigger (re)start of adb daemon
1450
+  property_set("lineage.service.adb.root", "1");
1451
+}
1452
+
1336 1453
 int main(int argc, char **argv) {
1337 1454
   // We don't have logcat yet under recovery; so we'll print error on screen and
1338 1455
   // log to stdout (which is redirected to recovery.log) as we used to do.
@@ -1359,17 +1476,46 @@ int main(int argc, char **argv) {
1359 1476
     return 0;
1360 1477
   }
1361 1478
 
1362
-  time_t start = time(nullptr);
1479
+  // Handle alternative invocations
1480
+  char* command = argv[0];
1481
+  char* stripped = strrchr(argv[0], '/');
1482
+  if (stripped) {
1483
+    command = stripped + 1;
1484
+  }
1485
+
1486
+  if (strcmp(command, "recovery") != 0) {
1487
+    struct recovery_cmd cmd = get_command(command);
1488
+    if (cmd.name) {
1489
+      return cmd.main_func(argc, argv);
1490
+    }
1491
+
1492
+    if (!strcmp(command, "setup_adbd")) {
1493
+      setup_adbd();
1494
+      return 0;
1495
+    }
1496
+    LOG(ERROR) << "Unhandled command " << command;
1497
+    return 1;
1498
+  }
1499
+
1500
+  // Clear umask for packages that copy files out to /tmp and then over
1501
+  // to /system without properly setting all permissions (eg. gapps).
1502
+  umask(0);
1363 1503
 
1364 1504
   // redirect_stdio should be called only in non-sideload mode. Otherwise
1365 1505
   // we may have two logger instances with different timestamps.
1366 1506
   redirect_stdio(TEMPORARY_LOG_FILE);
1367 1507
 
1368
-  printf("Starting recovery (pid %d) on %s", getpid(), ctime(&start));
1369
-
1370 1508
   load_volume_table();
1371 1509
   has_cache = volume_for_mount_point(CACHE_ROOT) != nullptr;
1372 1510
 
1511
+  copy_userdata_files();
1512
+  set_time();
1513
+  setup_adbd();
1514
+
1515
+  time_t start = time(nullptr);
1516
+
1517
+  printf("Starting recovery (pid %d) on %s", getpid(), ctime(&start));
1518
+
1373 1519
   std::vector<std::string> args = get_args(argc, argv);
1374 1520
   std::vector<char*> args_to_parse(args.size());
1375 1521
   std::transform(args.cbegin(), args.cend(), args_to_parse.begin(),

+ 34
- 0
recovery_cmds.h View File

@@ -0,0 +1,34 @@
1
+/*
2
+ * Copyright (C) 2013 The CyanogenMod Project
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *      http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+#ifndef _RECOVERY_CMDS_H
18
+#define _RECOVERY_CMDS_H
19
+
20
+#ifdef __cplusplus
21
+extern "C" {
22
+#endif
23
+
24
+int reboot_main(int argc, char **argv);
25
+int poweroff_main(int argc, char **argv);
26
+int start_main(int argc, char **argv);
27
+int stop_main(int argc, char **argv);
28
+int mksh_main(int argc, char **argv);
29
+
30
+#ifdef __cplusplus
31
+}
32
+#endif
33
+
34
+#endif