当前位置: 首页 > 工具软件 > sg3_utils > 使用案例 >

如何移植sg3_utils到andriod系统中

章远航
2023-12-01

1.本文章遵从” 署名-非商业性使用 2.5 中国大陆 (CC BY-NC 2.5 CN)”

2.  转载或引用本文档中的内容须注明 “资料来源:HB@ Technical Document” 字样




Sg3_utils包含各种可以从用户空间发命令到scsi设备, 这篇文章主要告诉大家如何移植sg3_utils到ARM平台上。 之前我们主要用sg3_utils是在台式机或者直接复制它到目标机上去编译, 但对于大多数嵌入式设备来说, 我们需要交叉编译,尤其是对于android系统, 如果external下面没有所需要的工具包时, 我们必须对它进行交叉编译。为什么要把sg3-utils的交叉编译写一篇文章呢?只要是在我自己交叉编译的过程中,发现了一些问题,这里只是作一个总结,以帮助后来者少走弯路。

Step1: Download sg3_utils source code

 

Sg3_utils的官网是在http://sg.danny.cz/sg/sg3_utils.html,你可以从这里读取第一手的关于sg3_utils的介绍, 我在这里就不啰嗦了。在这个页面的最下方有它的下载地址。对于熟悉github的朋友可以用git clone下载, 你也可以下载压缩版本的。

 

其中要说明的是,上面两个github的下载地址, 一个是来此SUSE公司的Hannes Reinecke, 另一个是来此SDC的Bart Van Assche, 他根据自己的需求有可能会在各自的分支上加入一些自己的应用,anyway, 这两个你可以认选一个,eg”

Git clone https://github.com/bvanassche/sg3_utils.git

 注: 你也可以从我个人的github上下载:

https://github.com/beanhuo/sg3_utils.git   sg3_utils-1.43-for-android

Step 2: Create Standalone Toolchain

这里要说明的是,如果你用linaro的gcc,编译出的来ELF可执行文件,所需要的interpreter的地址是/lib/ld-linux-aarch64.so,而androidinterpreter/system/bin/linker6。你可以把sg3_utils放到external下去编译,但这又需要一些时间。我的方法是构建自己的standalone toolchain来编译。

编译之前我们来下载NDK:

https://developer.android.com/ndk/downloads/older_releases.html#ndk-15c-downloads

这里有好多版本,我建议大家还是下载最新的版本,因为fix了一些之前版本的bug,相对稳定。

如果你用老一版本,很有可能在编译时,会出现下面的问题1:

./include/sg_linux_inc.h:14:25: fatal error: scsi/sg.h: No such file or directory   #include <scsi/sg.h>

他这这里描述的问题是一样的:https://karkhaz.github.io/tuscan/android/sg3_utils.html#162

具体为什么会出现上面的原因,这里我们就不多说了, 我们的最终目的是要编译通过。

OK,我这里下载的是Android NDK, Revision 15c (July 2017),一个最新的版本。

它是一个zip格式的压缩文件,没关系linux可以解压任何格式的压缩文件,只要你想的到。

unzipandroid-ndk-r15c-linux-x86_64.zip

解压完, 我们获得一个android-ndk-r15c的文件夹,它里面就是NDK的源文件。

关于如何创建standalone toolchain网上有好多的介绍,如https://gist.github.com/Tydus/11109634

你可以安照上面的去做,但我不知道在编译的时候会出现什么问题,这里我只说我自己的,如下:

android-ndk-r15/build/tools/make_standalone_toolchain.py \

    --arch arm64 --api 26 --install-dir/ubuntu/crosstools/my-android-arm64-toolchain

这里要想说的,不要用make-standalone-toolchain.sh去创建,这之前是用它去的,但发现会出现如下的问题:

./libcrypto.so: error: undefined reference to 'stdin'
./libcrypto.so: error: undefined reference to 'signal'
./libcrypto.so: error: undefined reference to 'tcsetattr'
./libcrypto.so: error: undefined reference to 'tcgetattr'
collect2: error: ld returned 1 exit status

同时也不要用--deprecated-headers选项,因为如果加了它,上面的问题1会出现。OK.

经过上面的命令后,会在你所指定的目录下出现我们想要的standalone toolchain:

root@bean-ubuntu:/ubuntu/crosstools/my-android-arm64-toolchain# ls

drwxr-xr-x  5 root root   4096 dec   11 22:35 aarch64-linux-android

-rw-r--r--  1 root root     11 júl   21 11:03 AndroidVersion.txt

drwxr-xr-x 10 root root   4096 dec   11 22:35 bin

-rw-r--r--  1 root root  18002 júl   21 11:04 COPYING

-rw-r--r--  1 root root  35147 júl   21 11:04 COPYING3

-rw-r--r--  1 root root   7639 júl   21 11:04 COPYING3.LIB

-rw-r--r--  1 root root  26527 júl   21 11:04 COPYING.LIB

-rw-r--r--  1 root root   3324 júl   21 11:04 COPYING.RUNTIME

drwxr-xr-x  4 root root   4096 dec   11 22:35 include

drwxr-xr-x  7 root root   4096 dec   11 22:35 lib

drwxr-xr-x  3 root root   4096 dec   11 22:35 lib64

drwxr-xr-x  3 root root   4096 dec   11 22:35 libexec

-rw-r--r--  1 root root      0 júl   21 11:03 MODULE_LICENSE_BSD_LIKE

-rw-r--r--  1 root root      0 júl   21 11:04 MODULE_LICENSE_GPL

-rw-r--r--  1 root root      0 júl   21 11:03 MODULE_LICENSE_MIT

-rw-r--r--  1 root root 125319 júl   21 11:08 NOTICE

drwxr-xr-x  5 root root   4096 dec   11 22:35 prebuilt_include

-rw-r--r--  1 root root   4465 júl   21 11:08 repo.prop

drwxr-xr-x  5 root root   4096 dec   11 22:35 share

drwxr-xr-x  3 root root   4096 júl   21 11:04 sysroot

drwxr-xr-x  7 root root   4096 dec   11 22:35 test

drwxr-xr-x  4 root root   4096 dec   11 22:35 tools

其中在bin目录下, 就是我们所要的一此gcc的交叉编译文件。

Step 3: Configure/make/makeinstall sg3_utils

1.  申明你的交叉编译工具的路径:

exportPATH=$PATH:/home/ubuntu/crosstools/my-android-arm64-toolchain/bin

2.  Configure

./configure CFLAGS=-static --prefix=/home/sg3_utils/out/ \

--host=aarch64-linux-android LD=aarch64-linux-android-ld CC=aarch64-linux-android-gcc

一般上面的configure命令不会出错,这里是用GNU automake来去根据你的配制来生成makefile文件, 关于GNU automake我会写一篇专问的文章。

3.   Make

当make时这里有一个小问题,会有下面的问题:

Making all in src

make[2]: Entering directory '/home/workspace/micron/00_job_EBU/06_hikey960/source_code/android/external/sg3_utils/src'

/bin/sh ../libtool  --tag=CC   --mode=link aarch64-linux-android-gcc -Wall -W  -static   -o sgp_dd sgp_dd.o ../lib/libsgutils2.la -lpthread -lm 

libtool: link: aarch64-linux-android-gcc -Wall -W -o sgp_dd sgp_dd.o  ../lib/.libs/libsgutils2.a -lpthread -lm

/home/ubuntu/crosstools/my-android-arm64-toolchain/bin/../lib/gcc/aarch64-linux-android/4.9.x/../../../../aarch64-linux-android/bin/ld: cannot find -lpthread

collect2: error: ld returned 1 exit status

Makefile:990: recipe for target 'sgp_dd' failed

make[2]: *** [sgp_dd] Error 1

make[2]: Leaving directory '/home/workspace/micron/00_job_EBU/06_hikey960/source_code/android/external/sg3_utils/src'

Makefile:401: recipe for target 'all-recursive' failed

make[1]: *** [all-recursive] Error 1

make[1]: Leaving directory '/home/workspace/micron/00_job_EBU/06_hikey960/source_code/android/external/sg3_utils'

Makefile:333: recipe for target 'all' failed

make: *** [all] Error 2

如果去src/Makefile,对于sgp_dd.c的编译,多了一个-lpthread,

sgp_dd_LDADD = ../lib/libsgutils2.la -lpthread

网上有好多版本的说法,因为我不需要sgp_dd这个工具, 所以这里我直接注消掉-lpthread,

sgp_dd_LDADD = ../lib/libsgutils2.la  // -lpthread

同时也要注消掉在sgp_dd.c 中对于pthread_cancel的调用。

1632   // status = pthread_cancel(sig_listen_thread_id);                                                               

1633     if (0 != status) err_exit(status, "pthread_cancel"); 

主要原因是,android Bionic C library是不支持pthread_cancel,我们可以用signal来取代pthread_cancel.具体patch如下, 你也可以从我的github上下载fixed 版本。

---
 configure       | 30 ++++++++++++++++++++++++++++++
 configure.ac    |  6 ++++++
 src/Makefile.am |  4 ++++
 src/sgp_dd.c    | 17 +++++++++++++++++
 4 files changed, 57 insertions(+)

diff --git a/configure b/configure
index 9958be2..d9f23f2 100755
--- a/configure
+++ b/configure
@@ -635,6 +635,8 @@ ac_subst_vars='am__EXEEXT_FALSE  am__EXEEXT_TRUE  LTLIBOBJS  LIBOBJS
+OS_ANDROID_FALSE
+OS_ANDROID_TRUE
 OS_WIN32_CYGWIN_FALSE
 OS_WIN32_CYGWIN_TRUE
 OS_WIN32_MINGW_FALSE
@@ -12292,6 +12294,21 @@ _ACEOF
 
 
 case "${host}" in
+        *-*-android*)
+
+cat >>confdefs.h <<_ACEOF
+#define SG_ON_ANDROID 1
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define SG_LIB_LINUX 1
+_ACEOF
+
+                os_cflags=''
+
+                os_libs=''
+ ;;
         *-*-linux-gnu*)
 
 cat >>confdefs.h <<_ACEOF
@@ -12428,6 +12445,14 @@ else
   OS_WIN32_CYGWIN_FALSE=
 fi
 
+ if echo $host_os | grep 'android' > /dev/null; then
+  OS_ANDROID_TRUE=
+  OS_ANDROID_FALSE='#'
+else
+  OS_ANDROID_TRUE='#'
+  OS_ANDROID_FALSE=
+fi
+
 
 # Check whether --enable-linuxbsg was given.
 if test "${enable_linuxbsg+set}" = set; then :
@@ -12624,6 +12649,10 @@ if test -z "${OS_WIN32_CYGWIN_TRUE}" && test -z "${OS_WIN32_CYGWIN_FALSE}"; then
   as_fn_error $? "conditional \"OS_WIN32_CYGWIN\" was never defined.
 Usually this means the macro was only invoked conditionally." "$LINENO" 5  fi
+if test -z "${OS_ANDROID_TRUE}" && test -z "${OS_ANDROID_FALSE}"; then
+  as_fn_error $? "conditional \"OS_ANDROID\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 
+5 fi
 
 : "${CONFIG_STATUS=./config.status}"
 ac_write_fail=0
@@ -14211,6 +14240,7 @@ $as_echo X"$file" |
     cat <<_LT_EOF >> "$cfgfile"
 #! $SHELL
 # Generated automatically by $as_me ($PACKAGE) $VERSION
+# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
 # NOTE: Changes made to this file will be lost: look at ltmain.sh.
 
 # Provide generalized library-building support services.
diff --git a/configure.ac b/configure.ac index 6c35d1a..cef0686 100644
--- a/configure.ac
+++ b/configure.ac
@@ -37,6 +37,11 @@ AC_CANONICAL_HOST
 AC_DEFINE_UNQUOTED(SG_LIB_BUILD_HOST, "${host}", [sg3_utils Build Host])
 
 case "${host}" in
+        *-*-android*)
+		AC_DEFINE_UNQUOTED(SG_ON_ANDROID, 1, [sg3_utils on android])
+		AC_DEFINE_UNQUOTED(SG_LIB_LINUX, 1, [sg3_utils on linux])
+                AC_SUBST([os_cflags], [''])
+                AC_SUBST([os_libs], ['']) ;;
         *-*-linux-gnu*)
 		AC_DEFINE_UNQUOTED(SG_LIB_LINUX, 1, [sg3_utils on linux])
                 AC_SUBST([os_cflags], ['']) @@ -79,6 +84,7 @@ AM_CONDITIONAL(OS_OSF, [echo $host_os | grep '^osf' > /dev/null])  AM_CONDITIONAL(OS_SOLARIS, [echo $host_os | grep '^solaris' > /dev/null])  AM_CONDITIONAL(OS_WIN32_MINGW, [echo $host_os | grep '^mingw' > /dev/null])  AM_CONDITIONAL(OS_WIN32_CYGWIN, [echo $host_os | grep '^cygwin' > /dev/null])
+AM_CONDITIONAL(OS_ANDROID, [echo $host_os | grep 'android' > 
+/dev/null])
 
 AC_ARG_ENABLE([linuxbsg],
   AC_HELP_STRING([--disable-linuxbsg], [ignore linux bsg (sgv4) if present]), diff --git a/src/Makefile.am b/src/Makefile.am index 1012a78..daada79 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -86,7 +86,11 @@ sg_modes_LDADD = ../lib/libsgutils2.la @os_libs@
 
 sg_opcodes_LDADD = ../lib/libsgutils2.la @os_libs@
 
+if OS_ANDROID
+sgp_dd_LDADD = ../lib/libsgutils2.la @os_libs@ else
 sgp_dd_LDADD = ../lib/libsgutils2.la @os_libs@ -lpthread
+endif
 
 sg_persist_LDADD = ../lib/libsgutils2.la @os_libs@
 
diff --git a/src/sgp_dd.c b/src/sgp_dd.c index e154555..d59167c 100644
--- a/src/sgp_dd.c
+++ b/src/sgp_dd.c
@@ -1121,6 +1121,11 @@ process_flags(const char * arg, struct flags_t * fp)
     return 0;
 }
 
+void
+thread_exit_handler(int sig)
+{
+    pthread_exit(0);
+}
 
 #define STR_SZ 1024
 #define INOUTF_SZ 512
@@ -1147,6 +1152,14 @@ main(int argc, char * argv[])
     int in_sect_sz, out_sect_sz, status, n, flags;
     void * vp;
     char ebuff[EBUFF_SZ];
+#if SG_ON_ANDROID
+    struct sigaction actions;
+    memset(&actions, 0, sizeof(actions));
+    sigemptyset(&actions.sa_mask);
+    actions.sa_flags = 0;
+    actions.sa_handler = thread_exit_handler;
+    sigaction(SIGUSR1,&actions,NULL);
+#endif
 
     memset(&rcoll, 0, sizeof(Rq_coll));
     rcoll.bpt = DEF_BLOCKS_PER_TRANSFER; @@ -1629,7 +1642,11 @@ main(int argc, char * argv[])
         }
     }
 
+#if SG_ON_ANDROID
+    status = pthread_kill(sig_listen_thread_id, SIGUSR1); #else
     status = pthread_cancel(sig_listen_thread_id);
+#endif
     if (0 != status) err_exit(status, "pthread_cancel");
     if (STDIN_FILENO != rcoll.infd)
         close(rcoll.infd);
--
2.7.4


4.   Make install

经过make install之前,我会在out目录下得到我们所要的目标文件,这时只要把bin下的ELF文件,根据你的需要adb push到你的android目标板上就可以了。

Problem 1:  Android 5.0 "error: only positionindependent executables (PIE) are supported

经过上面的各个步骤之后, 我们有了ELF文件,但对新版本的android,对于在external之外编译的ELF可执行文件,会出现“onlyposition independent executables (-fPIE) are supported”

加入LOCAL_CFLAGS += -fPIE

LOCAL_LDFLAGS += -fPIE -pie

 于直接使用gcc的,可以直接加CFLAGS中加-fPIE -pie就可以

 类似资料: