recovery模式下支持ADB连接和串口操作

嵌入式Linux

共 4926字,需浏览 10分钟

 ·

2020-11-21 19:15

前言

Android平台下我们有时候会进入recovery下做一些操作,不管是通过ADB连接还是通过串口操作,都需要你的平台支持,不支持的话可以按照我们这篇文章进行修改。

正文

ADB连接

进入recovery后,我通过ADB连接会有如下报错

exec "/system/bin/sh": No such file or directory
1

根据提示,应该是需要把sh打包到recovery.img里面,不过这里要注意的是,recovery下执行的bin文件需要静态编译才行,所以我们需要修改sh编译的Android.bp文件:

diff --git a/external/mksh/Android.bp b/external/mksh/Android.bp
index 2bca561e9d..5fb3c67ad7 100644
--- a/external/mksh/Android.bp
+++ b/external/mksh/Android.bp
@@ -120,6 +120,7 @@ cc_defaults {

 cc_binary {
     name: "sh",
+    static_executable: true,
     defaults: ["sh-defaults"],
 }
1234567891011

然后将编译出来的sh文件打包到recovery.img里面:

diff --git a/build/make/core/Makefile b/build/make/core/Makefile
index c58eb39839..027a32aee8 100644
--- a/build/make/core/Makefile
+++ b/build/make/core/Makefile
@@ -1398,6 +1398,8 @@ define build-recoveryimage-target
     cp -rf $(item) $(TARGET_RECOVERY_ROOT_OUT)/$(newline))
   $(hide) $(foreach item,$(recovery_fstab), \
     cp -f $(item) $(TARGET_RECOVERY_ROOT_OUT)/etc/recovery.fstab)
+  $(hide) mkdir -p $(TARGET_RECOVERY_ROOT_OUT)/system/bin
+  $(hide) cp -r $(PRODUCT_OUT)/system/bin/sh $(TARGET_RECOVERY_ROOT_OUT)/system/bin
   $(if $(strip $(recovery_wipe)), \
     $(hide) cp -f $(recovery_wipe) $(TARGET_RECOVERY_ROOT_OUT)/etc/recovery.wipe)
   $(hide) cp $(RECOVERY_INSTALL_OTA_KEYS) $(TARGET_RECOVERY_ROOT_OUT)/res/keys
@@ -1411,9 +1413,7 @@ define build-recoveryimage-target
   $(hide) ln -sf prop.default $(TARGET_RECOVERY_ROOT_OUT)/default.prop
   $(BOARD_RECOVERY_IMAGE_PREPARE)
   $(if $(filter true,$(BOARD_BUILD_SYSTEM_ROOT_IMAGE)), \
-    $(hide) mkdir -p $(TARGET_RECOVERY_ROOT_OUT)/system_root; \
-            rm -rf $(TARGET_RECOVERY_ROOT_OUT)/system; \
-            ln -sf /system_root/system $(TARGET_RECOVERY_ROOT_OUT)/system) # Mount the system_root_image to /system_root and symlink /system.
+    $(hide) mkdir -p $(TARGET_RECOVERY_ROOT_OUT)/system_root;)
   $(hide) $(MKBOOTFS) -d $(TARGET_OUT) $(TARGET_RECOVERY_ROOT_OUT) | $(MINIGZIP) > $(recovery_ramdisk)
   $(if $(filter true,$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_VBOOT)), \
     $(hide) $(MKBOOTIMG) $(INTERNAL_RECOVERYIMAGE_ARGS) $(INTERNAL_MKBOOTIMG_VERSION_ARGS) $(BOARD_MKBOOTIMG_ARGS) --output $(1).unsigned, \
123456789101112131415161718192021222324

以上操作后,就能正常ADB连接设备了。

串口操作

想要串口也能操作,也同样需要上面的步骤,除此之外还需要额外的修改,在进入recovery后需要拉起console服务:

diff --git a/device/emdoor/em_t6230_p4mme/init.recovery.mt8167.rc b/device/emdoor/em_t6230_p4mme/init.recovery.mt8167.rc
old mode 100644
new mode 100755
index f8ff23c8de..bb0087a70b
--- a/device/emdoor/em_t6230_p4mme/init.recovery.mt8167.rc
+++ b/device/emdoor/em_t6230_p4mme/init.recovery.mt8167.rc
@@ -14,12 +14,29 @@ on init
     mkdir /config/usb_gadget/g1/configs/b.1 0777 shell shell
     mkdir /config/usb_gadget/g1/configs/b.1/strings/0x409 0770 shell shell
     mkdir /config/usb_gadget/g1/functions/ffs.adb
+
+on post-fs
+    # start console service earlier here
+    start console
+
+on property:ro.debuggable=1
+    start console
+
+service console /system/bin/sh
+    class core
+    console
+    disabled
+    user root
+    group shell log readproc
+    seclabel u:r:shell:s0
+    setenv HOSTNAME console

 on property:ro.debuggable=0
        # distinguish USB shoulde connect or not, i.e. CDP vs SDP
     write /sys/class/udc/musb-hdrc/device/cmode 2
     # set charging free due to it wait for USB activation
     start adbd
+    start console

 on property:sys.usb.ffs.ready=1
     write /config/usb_gadget/g1/UDC "none"
123456789101112131415161718192021222324252627282930313233343536

其它

虽然现在我们能ADB连接和串口操作了,但是常用的ls等命令却使用不了,因为recovery下system分区没有挂载,toybox和busybox等工具都没有,自然无法使用shell命令。这次我把toybox工具移植到recovery中,你也可以移植busybox和toolbox。

我们看external/toybox/Android.mk有专门编译给recovery使用的选项:

############################################
# static version to be installed in recovery
############################################

include $(CLEAR_VARS)
LOCAL_MODULE := toybox_static
LOCAL_SRC_FILES := $(common_SRC_FILES)
LOCAL_CFLAGS := $(common_CFLAGS)
LOCAL_STATIC_LIBRARIES := $(toybox_libraries)
# libc++_static is needed by static liblog
LOCAL_CXX_STL := libc++_static
LOCAL_MODULE_PATH := $(TARGET_RECOVERY_ROOT_OUT)/sbin
LOCAL_FORCE_STATIC_EXECUTABLE := true
LOCAL_POST_INSTALL_CMD := $(hide) $(foreach t,$(ALL_TOOLS),ln -sf ${LOCAL_MODULE} $(LOCAL_MODULE_PATH)/$(t);)
include $(BUILD_EXECUTABLE)
123456789101112131415

只要把编译的模块名toybox_static加入到下面的文件就可以了:

diff --git a/system/core/shell_and_utilities/Android.bp b/system/core/shell_and_utilities/Android.bp
index 2e42b70993..ec53e59de6 100644
--- a/system/core/shell_and_utilities/Android.bp
+++ b/system/core/shell_and_utilities/Android.bp
@@ -17,5 +17,6 @@ phony {
         "toolbox_vendor",
         "toybox",
         "toybox_vendor",
+        "toybox_static",
     ],
 }
1234567891011

结语

上面说了一大堆,其实最简单的方法只要在recovery启动的rc脚本中把system分区挂载一下就好了(逃~)。


推荐阅读:
    专辑|Linux文章汇总
    专辑|程序人生
    专辑|C语言

嵌入式Linux
微信扫描二维码,关注我的公众号 
浏览 132
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报