├── META-INF └── com │ └── google │ └── android │ ├── updater-script │ └── update-binary ├── uninstall.sh ├── module.prop ├── post-fs-data.sh ├── mkshrc ├── LICENSE.txt ├── profile ├── service.sh ├── README.md └── customize.sh /META-INF/com/google/android/updater-script: -------------------------------------------------------------------------------- 1 | #MAGISK 2 | -------------------------------------------------------------------------------- /uninstall.sh: -------------------------------------------------------------------------------- 1 | #!/system/bin/sh 2 | 3 | ENTWARE_INSTALLATION_PATH="/data/entware-magisk" 4 | if ! [ -f "$ENTWARE_INSTALLATION_PATH/.keep" ]; then 5 | rm -rf "$ENTWARE_INSTALLATION_PATH" 6 | fi 7 | 8 | unset ENTWARE_INSTALLATION_PATH 9 | -------------------------------------------------------------------------------- /module.prop: -------------------------------------------------------------------------------- 1 | id=entware-magisk 2 | name=Entware Installer 3 | version=1.0.1 4 | versionCode=010000 5 | author=Artem Boldariev https://chaoticlab.io 6 | description=This module contains unofficial Entware installer and supplementary initialisation scripts for Android devices rooted with Magisk. -------------------------------------------------------------------------------- /post-fs-data.sh: -------------------------------------------------------------------------------- 1 | #!/system/bin/sh 2 | 3 | if [ -z "$MODPATH" ]; then 4 | MODPATH="/data/adb/modules/entware-magisk" 5 | fi 6 | 7 | # Create empty login shell and interactive shell initialisation script files if necessary. 8 | for script in profile mkshrc 9 | do 10 | SCRIPT_FILE="/system/etc/$script" 11 | if ! [ -r "$SCRIPT_FILE" ] && ! [ -r "${MODPATH}${SCRIPT_FILE}" ]; then 12 | echo "# This is a dummy \"$SCRIPT_FILE\" file created by \"$MODPATH/post-fs-data.sh\"." > "${MODPATH}${SCRIPT_FILE}" 13 | elif [ -r "$SCRIPT_FILE" ] && [ -r "${MODPATH}${SCRIPT_FILE}" ]; then 14 | rm -f "${MODPATH}${SCRIPT_FILE}" 15 | fi 16 | unset SCRIPT_FILE 17 | done 18 | -------------------------------------------------------------------------------- /mkshrc: -------------------------------------------------------------------------------- 1 | #!/system/bin/sh 2 | 3 | # ENTWARE_PROFILE is defined in /system/etc/mkshrc and in 4 | # /system/etc/profile. See the Magisk's Entware startup script for 5 | # additional details (usually /data/adb/modules/entware-magisk/entware.sh). 6 | 7 | # Load profile (if required) - most of the terminal emulators on Android 8 | # do not invoke the login shell. Thus, we are going to load the file manually 9 | # to initialise the environmental variables properly (including PATH). 10 | # 11 | # PROFILE_SCRIPT_LOADED is defined in profile to avoid extra profile invocation. 12 | if [ -r "$ENTWARE_PROFILE" ] && [ "$PROFILE_SCRIPT_LOADED" != "$(id -u)" ]; then 13 | . "$ENTWARE_PROFILE" 14 | fi 15 | 16 | # Load user interactive shell initialisation file. 17 | if [ -n "$HOME" ] && [ -r "$HOME/.mkshrc" ]; then 18 | . "$HOME/.mkshrc" 19 | fi 20 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | MIT/Expat License 2 | 3 | Copyright (c) 2020 Artem Boldariev 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /profile: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # In most cases, you do NOT want to load this file directly. It is 3 | # better to use /etc/profile as usual (which should in turn load this 4 | # file). Also, it is better to not modify this file. Please put your 5 | # customisation files into "profile.d" directory. 6 | 7 | PROFILE_SCRIPT_LOADED="$(id -u)" # see mkshrc for details. 8 | export PROFILE_SCRIPT_LOADED 9 | 10 | # ANDROID_START_ENV_FILE and ENTWARE_PROFILE are defined in 11 | # /system/etc/mkshrc and in /system/etc/profile. See the Magisk's 12 | # Entware startup script for additional details (usually 13 | # /data/adb/modules/entware-magisk/service.sh). 14 | print_start_env () 15 | { 16 | if [ -n "$1" ] && [ -r "$ANDROID_START_ENV_FILE" ]; then 17 | grep -e "^$1=" "$ANDROID_START_ENV_FILE" 18 | fi 19 | } 20 | 21 | load_start_env_var() 22 | { 23 | if [ -n "$1" ]; then 24 | LOADED_VAR="$(print_start_env "$1")" 25 | if [ -n "$LOADED_VAR" ]; then 26 | eval "export $LOADED_VAR" 27 | fi 28 | fi 29 | unset LOADED_VAR 30 | } 31 | 32 | load_start_env_var_if_empty() 33 | { 34 | if [ -z "$(eval echo \"\$"$1"\")" ]; then 35 | load_start_env_var "$1" 36 | fi 37 | } 38 | 39 | # Set umask to a sane value. 40 | if [ "$(id -u)" -eq 0 ]; then 41 | umask 022 42 | else 43 | umask 077 44 | fi 45 | 46 | # Set HOME to the one defined in Entware. 47 | INITIAL_HOME="$HOME" # save the old value 48 | ENTWARE_HOME="$(su 0 -c cat /opt/etc/passwd | cut -d ':' -f 3,6 | grep -e "^$(id -u):" | cut -d ':' -f 2)" 49 | if [ -n "$ENTWARE_HOME" ]; then 50 | export HOME="$ENTWARE_HOME" 51 | if [ "$PWD" != "$HOME" ] && [ "$(echo "$0" | dd count=1 bs=1 2> /dev/null)" = "-" ]; then 52 | cd "$HOME" || echo "Cannot change directory to \"$HOME\"." 53 | fi 54 | fi 55 | unset ENTWARE_HOME 56 | 57 | # Default Android PATH 58 | load_start_env_var PATH 59 | 60 | # Entware 61 | if [ -d /opt/bin ]; then 62 | PATH="$PATH:/opt/bin" 63 | fi 64 | 65 | if [ "$(id -u)" -eq 0 ] && [ -d /opt/sbin ]; then 66 | PATH="$PATH:/opt/sbin" 67 | fi 68 | 69 | # Add the "bin" directory to PATH 70 | LOCALBIN="$(dirname "$ENTWARE_PROFILE")/bin" 71 | if [ -d "$LOCALBIN" ]; then 72 | PATH="$PATH:$LOCALBIN" 73 | fi 74 | unset LOCALBIN 75 | 76 | # Add the ~/bin directory to PATH 77 | USERBIN="$HOME/bin" 78 | if [ -n "$HOME" ] && [ -d "$USERBIN" ]; then 79 | PATH="$PATH:$USERBIN" 80 | fi 81 | unset USERBIN 82 | 83 | export PATH 84 | 85 | if [ -d /opt/share/terminfo ]; then 86 | export TERMINFO=/opt/share/terminfo 87 | fi 88 | 89 | # Set location of the temporary directory. 90 | # Please notice that we are going to prefer ~/tmp if it exist. 91 | # It might be necessary because of SELinux limitations. 92 | if [ -n "$HOME" ] && [ -d "$HOME/tmp" ]; then 93 | export TMP="$HOME/tmp" 94 | export TEMP="$HOME/tmp" 95 | elif [ -d /opt/tmp ]; then 96 | export TMP=/opt/tmp 97 | export TEMP=/opt/tmp 98 | fi 99 | 100 | # Load values of some Android environmental variables. Native android 101 | # tools might complain if these are not set. This might happen when 102 | # accessing the device via SSH. 103 | load_start_env_var_if_empty ANDROID_ROOT 104 | load_start_env_var_if_empty ANDROID_DATA 105 | load_start_env_var_if_empty ANDROID_ASSETS 106 | load_start_env_var_if_empty EXTERNAL_STORAGE 107 | load_start_env_var_if_empty ANDROID_PROPERTY_WORKSPACE 108 | load_start_env_var_if_empty ASEC_MOUNTPOINT 109 | 110 | unset ANDROID_START_ENV_FILE 111 | 112 | # Load files from profile.d 113 | if [ -d "$ENTWARE_PROFILE.d" ]; then 114 | for profile in "$ENTWARE_PROFILE.d/"*.sh; do 115 | [ -r "$profile" ] && . "$profile" 116 | done 117 | unset profile 118 | fi 119 | 120 | # Try to load ~/.profile if no such file were loaded before setting 121 | # HOME to ENTWARE_HOME. 122 | if [ "$INITIAL_HOME" != "$HOME" ] && ! [ -r "$INITIAL_HOME/.profile" ] && [ -r "$HOME/.profile" ]; then 123 | . "$HOME/.profile" 124 | fi 125 | 126 | unset INITIAL_HOME 127 | -------------------------------------------------------------------------------- /META-INF/com/google/android/update-binary: -------------------------------------------------------------------------------- 1 | #!/sbin/sh 2 | 3 | ################# 4 | # Initialization 5 | ################# 6 | 7 | umask 022 8 | 9 | # echo before loading util_functions 10 | ui_print() { echo "$1"; } 11 | 12 | require_new_magisk() { 13 | ui_print "*******************************" 14 | ui_print " Please install Magisk v20.0+! " 15 | ui_print "*******************************" 16 | exit 1 17 | } 18 | 19 | ######################### 20 | # Load util_functions.sh 21 | ######################### 22 | 23 | OUTFD=$2 24 | ZIPFILE=$3 25 | 26 | mount /data 2>/dev/null 27 | 28 | [ -f /data/adb/magisk/util_functions.sh ] || require_new_magisk 29 | . /data/adb/magisk/util_functions.sh 30 | [ $MAGISK_VER_CODE -lt 20000 ] && require_new_magisk 31 | 32 | if [ $MAGISK_VER_CODE -ge 20400 ]; then 33 | # New Magisk have complete installation logic within util_functions.sh 34 | install_module 35 | exit 0 36 | fi 37 | 38 | ################# 39 | # Legacy Support 40 | ################# 41 | 42 | TMPDIR=/dev/tmp 43 | PERSISTDIR=/sbin/.magisk/mirror/persist 44 | 45 | is_legacy_script() { 46 | unzip -l "$ZIPFILE" install.sh | grep -q install.sh 47 | return $? 48 | } 49 | 50 | print_modname() { 51 | local authlen len namelen pounds 52 | namelen=`echo -n $MODNAME | wc -c` 53 | authlen=$((`echo -n $MODAUTH | wc -c` + 3)) 54 | [ $namelen -gt $authlen ] && len=$namelen || len=$authlen 55 | len=$((len + 2)) 56 | pounds=$(printf "%${len}s" | tr ' ' '*') 57 | ui_print "$pounds" 58 | ui_print " $MODNAME " 59 | ui_print " by $MODAUTH " 60 | ui_print "$pounds" 61 | ui_print "*******************" 62 | ui_print " Powered by Magisk " 63 | ui_print "*******************" 64 | } 65 | 66 | # Override abort as old scripts have some issues 67 | abort() { 68 | ui_print "$1" 69 | $BOOTMODE || recovery_cleanup 70 | [ -n $MODPATH ] && rm -rf $MODPATH 71 | rm -rf $TMPDIR 72 | exit 1 73 | } 74 | 75 | rm -rf $TMPDIR 2>/dev/null 76 | mkdir -p $TMPDIR 77 | 78 | # Preperation for flashable zips 79 | setup_flashable 80 | 81 | # Mount partitions 82 | mount_partitions 83 | 84 | # Detect version and architecture 85 | api_level_arch_detect 86 | 87 | # Setup busybox and binaries 88 | $BOOTMODE && boot_actions || recovery_actions 89 | 90 | ############## 91 | # Preparation 92 | ############## 93 | 94 | # Extract prop file 95 | unzip -o "$ZIPFILE" module.prop -d $TMPDIR >&2 96 | [ ! -f $TMPDIR/module.prop ] && abort "! Unable to extract zip file!" 97 | 98 | $BOOTMODE && MODDIRNAME=modules_update || MODDIRNAME=modules 99 | MODULEROOT=$NVBASE/$MODDIRNAME 100 | MODID=`grep_prop id $TMPDIR/module.prop` 101 | MODNAME=`grep_prop name $TMPDIR/module.prop` 102 | MODAUTH=`grep_prop author $TMPDIR/module.prop` 103 | MODPATH=$MODULEROOT/$MODID 104 | 105 | # Create mod paths 106 | rm -rf $MODPATH 2>/dev/null 107 | mkdir -p $MODPATH 108 | 109 | ########## 110 | # Install 111 | ########## 112 | 113 | if is_legacy_script; then 114 | unzip -oj "$ZIPFILE" module.prop install.sh uninstall.sh 'common/*' -d $TMPDIR >&2 115 | 116 | # Load install script 117 | . $TMPDIR/install.sh 118 | 119 | # Callbacks 120 | print_modname 121 | on_install 122 | 123 | # Custom uninstaller 124 | [ -f $TMPDIR/uninstall.sh ] && cp -af $TMPDIR/uninstall.sh $MODPATH/uninstall.sh 125 | 126 | # Skip mount 127 | $SKIPMOUNT && touch $MODPATH/skip_mount 128 | 129 | # prop file 130 | $PROPFILE && cp -af $TMPDIR/system.prop $MODPATH/system.prop 131 | 132 | # Module info 133 | cp -af $TMPDIR/module.prop $MODPATH/module.prop 134 | 135 | # post-fs-data scripts 136 | $POSTFSDATA && cp -af $TMPDIR/post-fs-data.sh $MODPATH/post-fs-data.sh 137 | 138 | # service scripts 139 | $LATESTARTSERVICE && cp -af $TMPDIR/service.sh $MODPATH/service.sh 140 | 141 | ui_print "- Setting permissions" 142 | set_permissions 143 | else 144 | print_modname 145 | 146 | unzip -o "$ZIPFILE" customize.sh -d $MODPATH >&2 147 | 148 | if ! grep -q '^SKIPUNZIP=1$' $MODPATH/customize.sh 2>/dev/null; then 149 | ui_print "- Extracting module files" 150 | unzip -o "$ZIPFILE" -x 'META-INF/*' -d $MODPATH >&2 151 | 152 | # Default permissions 153 | set_perm_recursive $MODPATH 0 0 0755 0644 154 | fi 155 | 156 | # Load customization script 157 | [ -f $MODPATH/customize.sh ] && . $MODPATH/customize.sh 158 | fi 159 | 160 | # Handle replace folders 161 | for TARGET in $REPLACE; do 162 | ui_print "- Replace target: $TARGET" 163 | mktouch $MODPATH$TARGET/.replace 164 | done 165 | 166 | if $BOOTMODE; then 167 | # Update info for Magisk Manager 168 | mktouch $NVBASE/modules/$MODID/update 169 | cp -af $MODPATH/module.prop $NVBASE/modules/$MODID/module.prop 170 | fi 171 | 172 | # Copy over custom sepolicy rules 173 | if [ -f $MODPATH/sepolicy.rule -a -e $PERSISTDIR ]; then 174 | ui_print "- Installing custom sepolicy patch" 175 | # Remove old recovery logs (which may be filling partition) to make room 176 | rm -f $PERSISTDIR/cache/recovery/* 177 | PERSISTMOD=$PERSISTDIR/magisk/$MODID 178 | mkdir -p $PERSISTMOD 179 | cp -af $MODPATH/sepolicy.rule $PERSISTMOD/sepolicy.rule || abort "! Insufficient partition size" 180 | fi 181 | 182 | # Remove stuffs that don't belong to modules 183 | rm -rf \ 184 | $MODPATH/system/placeholder $MODPATH/customize.sh \ 185 | $MODPATH/README.md $MODPATH/.git* 2>/dev/null 186 | 187 | ############# 188 | # Finalizing 189 | ############# 190 | 191 | cd / 192 | $BOOTMODE || recovery_cleanup 193 | rm -rf $TMPDIR 194 | 195 | ui_print "- Done" 196 | exit 0 197 | -------------------------------------------------------------------------------- /service.sh: -------------------------------------------------------------------------------- 1 | #!/system/bin/sh 2 | 3 | ## The changes made by this script are NOT permanent and, 4 | # thus, need to be repeated on each boot of the device. 5 | 6 | ENTWARE_INSTALLATION_PATH="/data/entware-magisk" 7 | ENTWARE_MKSHRC="$ENTWARE_INSTALLATION_PATH/mkshrc" 8 | ENTWARE_PROFILE="$ENTWARE_INSTALLATION_PATH/profile" 9 | ENTWARE="$ENTWARE_INSTALLATION_PATH/entware" 10 | 11 | ANDROID_START_ENV_FILE="$ENTWARE/var/run/start-env.sh" 12 | 13 | UNSLUNG="/opt/etc/init.d/rc.unslung" 14 | 15 | # set umask to a sane value 16 | umask 022 17 | 18 | # Check if Entware directory is available 19 | if ! [ -d "$ENTWARE" ]; then 20 | exit 1 21 | fi 22 | 23 | # ensure that some directories exist 24 | ensure_dir_exists() 25 | { 26 | if [ -n "$1" ] && ! [ -d "$1" ]; then 27 | mkdir -p "$1" 28 | if [ -n "$2" ]; then 29 | chmod "$2" "$1" 30 | fi 31 | fi 32 | } 33 | 34 | ensure_dir_exists "$ENTWARE/tmp" 777 35 | ensure_dir_exists "$ENTWARE/var" 36 | ensure_dir_exists "$ENTWARE/var/run" 755 37 | 38 | ## Here we try to tune the Android's filesystem to be more Unix 39 | ## compatible. It is going to work only on devices which use ramdisk 40 | ## (rootfs) for their root (/). 41 | if [ "$(grep rootfs /proc/mounts | cut -d " " -f 2)" = "/" ]; then 42 | # Make the root file system writable. 43 | mount -o rw,remount / 44 | 45 | # Link /bin to /system/bin to make /bin/sh accessible (for portable 46 | # scripts) 47 | if ! [ -d /bin ]; then 48 | ln -sf /system/bin /bin 49 | fi 50 | 51 | # Link /usr/bin to /system/bin to make /usr/bin/env accessible (again, 52 | # for portable scripts: #!/usr/bin/env ...) 53 | ENV_LOCATION="$(which env)" 54 | if ! [ -d /usr ] && [ -n "$ENV_LOCATION" ]; then 55 | mkdir /usr 56 | ln -sf "$(dirname "$ENV_LOCATION")" /usr/bin 57 | fi 58 | 59 | # Link /opt to the Entware directory. 60 | if ! [ -d /opt ]; then 61 | ln -sf "$ENTWARE" /opt 62 | fi 63 | 64 | # Link /var to /opt/var (mostly for busybox crond, if we are going to 65 | # use one). 66 | if ! [ -d /var ]; then 67 | ln -sf "$ENTWARE/var" /var 68 | fi 69 | 70 | # Create /tmp (again, mostly for Entware). 71 | if ! [ -d /tmp ]; then 72 | ln -sf "$ENTWARE/tmp" /tmp 73 | fi 74 | 75 | # Create /run. 76 | if ! [ -d /run ]; then 77 | ln -sf "$ENTWARE/var/run" /run 78 | fi 79 | 80 | # Link /lib64 (and /lib, just in case) to the Entware's /opt/lib to 81 | # run ordinary Linux executables built for conventional distributions 82 | # (if you are lucky enough to have recent enough kernel and glibc). 83 | # Additionally to that, one has to install 'ldconfig', if not 84 | # installed, (opkg install ldconfig) and run it to build the libraries 85 | # cache (and rerun it after installing and removing libraries). 86 | if ! [ -d /lib ]; then 87 | mkdir -p /lib 88 | fi 89 | 90 | if ! [ -d /lib64 ]; then 91 | mkdir -p /lib64 92 | fi 93 | 94 | if [ -d /lib ] && [ -d "$ENTWARE/lib" ]; then 95 | ln -s "$ENTWARE"/lib/ld-linux*.so* /lib 96 | fi 97 | 98 | if [ -d /lib64 ] && [ -d "$ENTWARE/lib" ]; then 99 | ln -s "$ENTWARE"/lib/ld-linux*.so* /lib64 100 | fi 101 | 102 | # Make the root filesystem read only again. 103 | mount -o ro,remount / 104 | fi 105 | 106 | # check if /opt is available 107 | if ! [ -d /opt ]; then 108 | # there is no point to continue 109 | exit 1 110 | fi 111 | 112 | # Mount some temporary file systems. 113 | if [ -d "$ENTWARE/tmp" ]; then 114 | mount -t tmpfs tmpfs "$ENTWARE/tmp" 115 | fi 116 | 117 | if [ -d "$ENTWARE/var/run" ]; then 118 | mount -t tmpfs -o size=1m tmpfs "$ENTWARE/var/run" 119 | fi 120 | 121 | ## Modify the system shell initialisation files. 122 | augment_rc () 123 | { 124 | if [ -d /opt/var/run ] && [ -n "$1" ] && [ -n "$2" ]; then 125 | SYSRC="$1" 126 | USERFILE="$2" 127 | TMPRC="/opt/var/run/$(basename "$SYSRC")" 128 | if [ -r "$SYSRC" ]; then 129 | cp "$SYSRC" "$TMPRC" 130 | else 131 | return 1 132 | fi 133 | { echo "# modifications to load a system wide initialisation file"; 134 | echo "# from \"$USERFILE\""; 135 | echo "ANDROID_START_ENV_FILE=\"$ANDROID_START_ENV_FILE\""; 136 | echo "export ENTWARE=\"$ENTWARE\""; 137 | echo "export ENTWARE_MKSHRC=\"$ENTWARE_MKSHRC\""; 138 | echo "export ENTWARE_PROFILE=\"$ENTWARE_PROFILE\""; 139 | echo "if [ -r \"$USERFILE\" ]; then"; 140 | echo " . \"$USERFILE\""; 141 | echo "fi"; } >> "$TMPRC" 142 | mount -o bind "$TMPRC" "$SYSRC" 143 | fi 144 | return 0 145 | } 146 | 147 | # Augment an interactive shell initialisation file to load our file. 148 | augment_rc "/system/etc/mkshrc" "$ENTWARE_MKSHRC" 149 | 150 | # Augment a login shell initialisation file to load our file. 151 | augment_rc "/system/etc/profile" "$ENTWARE_PROFILE" 152 | 153 | ## Save initial environment to restore some variables if they are not 154 | ## set. It might be necessary when accessing device via SSH. 155 | if [ -d "$(dirname "$ANDROID_START_ENV_FILE")" ]; then 156 | env > "$ANDROID_START_ENV_FILE" 157 | fi 158 | 159 | # Let's try to generate ld.so.cache for the first time 160 | if ! [ -f /opt/etc/ld.so.cache ] && [ -x /opt/sbin/ldconfig ]; then 161 | /opt/sbin/ldconfig 162 | fi 163 | 164 | ## Start Entware services 165 | if [ -x "$UNSLUNG" ]; then 166 | "$UNSLUNG" start 167 | fi 168 | 169 | exit 0 170 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Description 2 | 3 | This repository contains a [Magisk](https://magiskmanager.com/) module that can be used to install and run [Entware](https://entware.net/), the ultimate repository for embedded devices, on a rooted Android-powered device. The installer is *unofficial* - it is not affiliated with the Entware project directly, but in the process of installation it downloads and uses the latest version of the *official* installer. 4 | 5 | Entware, when being installed using this module, actually makes it possible for the [available software packages](https://bin.entware.net/armv7sf-k3.2/Packages.html) to extend the functionality of the Android-powered device and turn it into a more or less real Linux-powered system with a full-featured package manager. Nevertheless, the installation remains *systemless*: it does not make any modifications to the "system" partition and is fully reversible. 6 | 7 | The module was announced in [this post](https://chaoticlab.io/posts/entware-installer-for-magisk/). 8 | 9 | **This module should be compatible with most devices running Android 8 and below. For devices running Android 9 and newer manual intervention may be required before the installation. More on this below.** 10 | 11 | *If you find this project useful, you may want to support the author and make a small [donation](https://chaoticlab.io/donate/).* 12 | 13 | # Disclaimer 14 | 15 | The code in this repository comes with good intentions in mind but *with no warranty whatsoever*. Android-powered devices are numerous and I cannot physically guarantee that the module is going to work properly on all of them. I embodied numerous sanity checks into the code, and the changes made by the scripts are not destructive by nature. Nevertheless, anything happens. If during your quest you have bricked your device or lost any data and you think that it was caused by my code - sorry, I cannot help you. You may try to open an issue so that I can try to do something to prevent it from happening in the future (if it is in my powers). 16 | 17 | # Compatibility 18 | 19 | Installing this module on any device should be safe: if the device is not compatible, the installation fails. If it fails, then remove the module from within the "Magisk Manager." 20 | 21 | Regarding this module, there are two kinds of Android devices (you can read more on the topic [here](https://topjohnwu.github.io/Magisk/boot.html)): 22 | 23 | 1. The devices, whose root file system (`/`) is a RAM-drive (`rootfs`) or, in some cases, whose root file system appears as a RAM-drive because of Magisk. The list includes most of the devices running Android 8 and older, and some of the ones, which were released with Android 8 and later updated to Android 9. 24 | 2. The devices, whose root file system (`/`) is an actual partition (so-called "system-as-root" devices). The list includes most of the recent devices released with Android version 9 and newer. 25 | 26 | On the first kind of devices, this module works just fine. You may install the module and expect it to work without any additional actions from your side. 27 | 28 | On the second kind of devices, installation may require manual intervention because currently, Magisk lacks functionality to make reversible modifications to the root file system. You need to manually modify the "system" partition to include at least the following symbolic links before installation: 29 | 30 | ``` 31 | /opt -> /data/entware-magisk/entware 32 | /bin -> /system/bin 33 | ``` 34 | Please note that modifying the "system" partition makes the installation *non-systemless anymore*. Please do your research on how to make the required changes. As stated [here](https://github.com/topjohnwu/magisk_files/blob/6510533d6a8bb751152539919f57bb616c2405af/notes.md), in some cases, it might be impossible or dangerous. In other cases, it might be as easy as opening a shell with root privileges: 35 | 36 | ``` 37 | $ su -l 38 | ``` 39 | 40 | remounting root file system for reading and writing (**issuing the following command may tamper block verification on some devices**): 41 | 42 | ``` 43 | # mount -o remount,rw / 44 | ``` 45 | 46 | creating the required links: 47 | 48 | ``` 49 | # ln -sf /data/entware-magisk/entware /opt 50 | # ln -sf /system/bin /bin 51 | ``` 52 | 53 | and remounting root file system read-only: 54 | 55 | ``` 56 | # mount -o remount,ro / 57 | ``` 58 | 59 | After you have figured out how to make the required changes and made them, you may reinstall the module. Installation should complete without any errors. Everything else is taken care of by the module. 60 | 61 | # Installation 62 | 63 | Currently, this module is not available in the official repository of the Magisk modules. But you can install it manually: 64 | 65 | 1. Download the module to your phone's storage from the projects' [**Releases** section](../../releases/). 66 | 2. In **Magisk Manager**, open the sidebar and select **Modules**. 67 | 3. Hit the floating button with a plus sign, then locate the downloaded module. 68 | 4. Open it. It will begin installation right away. 69 | 5. Reboot your phone when prompted. 70 | 71 | The module installs Entware into `/data/entware-magisk/entware` directory. There are also additional support files and directories in the `/data/entware-magisk`, in particular: 72 | 73 | * `profile.d` - you can use this directory in the same way you would use `/etc/profile.d` on a conventional Linux installation; 74 | * `bin` - this directory gets added to the `PATH` environmental variable. 75 | 76 | Software from the Entware repository uses GNU C Library and, thus, does not use the name resolution facility of the Android OS. By default [Google Public DNS Resolver](https://developers.google.com/speed/public-dns) is used (8.8.8.8, 8.8.4.4) by this installer. You can change this later by editing the `/opt/etc/resolv.conf` file. 77 | 78 | Optionally, you may want to enable remote access to the device via SSH. To do so: 79 | 80 | 1. Open the shell with root privileges: `su -l` 81 | 2. Install `dropbear` package: `opkg install dropbear` 82 | 3. Set the password for the `root` account mapping: `/opt/bin/passwd` 83 | 4. Start the `dropbear` SSH-daemon (it should start automatically on the next boot): `/opt/etc/init.d/S51dropbear start` 84 | 85 | Please keep in mind that invoking the `/opt/bin/passwd` command will not change the password for your `root` account on the device. Entware maintains its own mappings for the existing user accounts (`/opt/etc/passwd`) and groups (`/opt/etc/group`). By default, these files contain only mappings for the `root` user account and group, but you can change them to suit your needs. 86 | 87 | # Uninstallation 88 | 89 | Uninstalling Entware, installed using this module, is straightforward: uninstall the module from within **Magisk Manager** and follow the instructions. 90 | 91 | Please note that by default doing so also **removes** the `/data/entware-magisk` directory. If you do not want this behaviour and want to keep the directory, you can create an empty file named `.keep` inside this directory (e.g. by invoking the command `touch /data/entware-magisk/.keep` from within a shell with root privileges). 92 | 93 | # See Also 94 | 1. [Opkg Package Manager](https://openwrt.org/docs/guide-user/additional-software/opkg) 95 | 2. [Entware Wiki](https://github.com/Entware/Entware/wiki) 96 | 3. [Magisk Documentation](https://topjohnwu.github.io/Magisk/) 97 | -------------------------------------------------------------------------------- /customize.sh: -------------------------------------------------------------------------------- 1 | #!/system/bin/sh 2 | 3 | # where we are going to put the support files 4 | ENTWARE_INSTALLATION_PATH="/data/entware-magisk" 5 | ENTWARE="${ENTWARE_INSTALLATION_PATH}/entware" 6 | 7 | # default DNS resolvers 8 | DNS1="8.8.8.8" 9 | DNS2="8.8.4.4" 10 | 11 | # print error message and exit 12 | die () 13 | { 14 | ui_print "$1" 15 | if [ -d "$ENTWARE_INSTALLATION_PATH" ] && [ -n "$(find "$ENTWARE_INSTALLATION_PATH" -mindepth 1 -maxdepth 1)" ]; then 16 | ui_print "You may want to clear \"$ENTWARE_INSTALLATION_PATH\", reboot your device, and start anew." 17 | fi 18 | abort "Installation has been aborted." 19 | } 20 | 21 | die_on_error () 22 | { 23 | STATUS=$? 24 | if [ "$STATUS" -ne 0 ]; then 25 | unset STATUS 26 | die "$1" 27 | fi 28 | $?=$STATUS 29 | unset STATUS 30 | } 31 | 32 | # Let's detect the compatible Entware architecture 33 | KERNEL_VERSION="$(cut -d ' ' -f 3 /proc/version)" 34 | KERNEL_VERSION_MAJOR="$(echo "$KERNEL_VERSION" | cut -d '.' -f 1)" 35 | KERNEL_VERSION_MINOR="$(echo "$KERNEL_VERSION" | cut -d '.' -f 2)" 36 | 37 | if [ "$ARCH" = "arm" ] && [ "$KERNEL_VERSION_MAJOR" -ge "3" ] && [ "$KERNEL_VERSION_MINOR" -ge "2" ]; then 38 | ENTWARE_ARCH="armv7sf-k3.2" 39 | elif [ "$ARCH" = "arm" ]; then 40 | ENTWARE_ARCH="armv7sf-k2.6" 41 | elif [ "$ARCH" = "arm64" ] && [ "$KERNEL_VERSION_MAJOR" -ge "3" ] && [ "$KERNEL_VERSION_MINOR" -ge "10" ]; then 42 | ENTWARE_ARCH="aarch64-k3.10" 43 | elif [ "$ARCH" = "arm64" ]; then 44 | ENTWARE_ARCH="armv7sf-k3.2" 45 | elif [ "$ARCH" = "x64" ] && [ "$KERNEL_VERSION_MAJOR" -ge "3" ] && [ "$KERNEL_VERSION_MINOR" -ge "2" ]; then 46 | ENTWARE_ARCH="x64-k3.2" 47 | elif [ "$ARCH" = "x64" ]; then 48 | ENTWARE_ARCH="x86-k2.6" 49 | elif [ "$ARCH" = "x86" ] && [ "$KERNEL_VERSION_MAJOR" -ge "3" ] && [ "$KERNEL_VERSION_MINOR" -ge "2" ] && [ "$(grep -c x86_64 /proc/version)" -gt 0 ]; then 50 | # Some x86 devices (most notably ASUS Zenfone 2) might have 32-bit 51 | # userspace, but 64-bit kernel and, thus, capable of running 52 | # 64-bit version of Entware. 53 | ui_print "Guessing that kernel is x86_64 compatible." 54 | ENTWARE_ARCH="x64-k3.2" 55 | elif [ "$ARCH" = "x86" ]; then 56 | ENTWARE_ARCH="x86-k2.6" 57 | fi 58 | 59 | if [ -z "$ENTWARE_ARCH" ]; then 60 | die "Cannot guess the Entware installation architecture!" 61 | fi 62 | 63 | ui_print "Entware $ENTWARE_ARCH is going to be installed into \"$ENTWARE\" with support files placed into \"$ENTWARE_INSTALLATION_PATH\"." 64 | ui_print "You can change the default primary and secondary DNS resolvers ($DNS1, $DNS2) after the installation by editing \"$ENTWARE\etc\resolv.conf\" (/opt/etc/resolv.conf)." 65 | ui_print "Make sure that you have a working Internet connection!" 66 | 67 | # Let's initialise the "system/etc" directory 68 | if ! [ -d "$MODPATH/system/etc" ]; then 69 | mkdir -p "$MODPATH/system/etc" 70 | die_on_error "Cannot create \"system/etc\"!" 71 | fi 72 | 73 | # resolv.conf link 74 | ln -sf "/opt/etc/resolv.conf" "$MODPATH/system/etc/resolv.conf" 75 | die_on_error "Cannot create \"system/etc/resolv.conf\" link!" 76 | 77 | # Let's initialise the "system/bin" directory 78 | if ! [ -d "$MODPATH/system/bin" ]; then 79 | mkdir -p "$MODPATH/system/bin" 80 | die_on_error "Cannot create \"system/bin\"!" 81 | fi 82 | 83 | # /bin/bash - for unportable scripts 84 | ln -sf "/opt/bin/bash" "$MODPATH/system/bin/bash" 85 | die_on_error "Cannot create \"system/bin/bash\" link!" 86 | 87 | # Initialise the installation directory 88 | for dir in bin profile.d entware 89 | do 90 | DIR="${ENTWARE_INSTALLATION_PATH}/${dir}" 91 | if ! [ -d "$DIR" ]; then 92 | mkdir -p "$DIR" 93 | die_on_error "Cannot create \"$DIR\"!" 94 | fi 95 | done 96 | unset DIR 97 | 98 | # install scripts 99 | for script in profile mkshrc 100 | do 101 | SCRIPT_SOURCE="${MODPATH}/${script}" 102 | SCRIPT_TARGET="${ENTWARE_INSTALLATION_PATH}/${script}" 103 | if ! [ -r "$SCRIPT_TARGET" ]; then 104 | cp -f "$SCRIPT_SOURCE" "$SCRIPT_TARGET" 105 | die_on_error "Cannot copy \"${script}\"!" 106 | chmod 644 "$SCRIPT_TARGET" 107 | die_on_error "Cannot set permissions on \"${script}\"!" 108 | fi 109 | done 110 | unset SCRIPT_SOURCE SCRIPT_TARGET 111 | 112 | 113 | # Install Entware 114 | if ! [ -x "${ENTWARE_INSTALLATION_PATH}/entware/bin/opkg" ]; then 115 | if [ "$(grep rootfs /proc/mounts | cut -d " " -f 2)" = "/" ]; then 116 | mount -o remount,rw / 117 | die_on_error "Cannot remount \"\\\" for read and write!" 118 | ln -sf "$ENTWARE" /opt 119 | die_on_error "Cannot create /opt!" 120 | if ! [ -d /bin ]; then 121 | ln -sf /system/bin /bin 122 | die_on_error "Cannot create /bin (-> /system/bin)!" 123 | fi 124 | mount -o remount,ro / 125 | die_on_error "Cannot remount \"\\\" readonly!" 126 | else 127 | ui_print "Your device appears to have a real-partition as the root file system. Hopefully, you have created the required links beforehand (see the module's documentation for details)." 128 | fi 129 | # check if /bin/sh available 130 | if ! [ -x /bin/sh ]; then 131 | die "POSIX-compatible shell is not available as \"/bin/sh\". It is impossible to continues the installation." 132 | fi 133 | 134 | # check if /opt points to Entware 135 | if ! [ -L /opt ] || ! [ "$(readlink /opt)" = "$ENTWARE" ]; then 136 | die "\"/opt\" does not exist or does not point to \"$ENTWARE\"." 137 | fi 138 | 139 | OLD_PWD="$PWD" 140 | cd "$ENTWARE" || die "Cannot change the working directory to \"$ENTWARE\"!" 141 | 142 | wget -O - "http://bin.entware.net/$ENTWARE_ARCH/installer/generic.sh" | sh 143 | die_on_error "Entware installation has failed!" 144 | 145 | echo "nameserver $DNS1" > /opt/etc/resolv.conf 146 | die_on_error "Cannot set the first DNS resolver!" 147 | echo "nameserver $DNS2" >> /opt/etc/resolv.conf 148 | die_on_error "Cannot set the second DNS resolver!" 149 | 150 | if [ -f /opt/etc/profile ]; then 151 | mv /opt/etc/profile /opt/etc/profile.bak 152 | die_on_error "Renaming \"/opt/etc/profile\" has failed!" 153 | fi 154 | ln -sf /etc/profile /opt/etc/profile 155 | die_on_error "Cannot link /opt/etc/profile to /etc/profile!" 156 | 157 | # create home for root 158 | if ! [ -d /opt/root ]; then 159 | mkdir -p /opt/root 160 | die_on_error "Creating /opt/root has failed!" 161 | chmod 700 /opt/root 162 | die_on_error "Setting permissions on /opt/root has failed!" 163 | fi 164 | 165 | # create a user mapping for the root user 166 | echo "root:x:0:0::/opt/root:/system/bin/sh" > /opt/etc/passwd 167 | die_on_error "Cannot create the user \"root\"!" 168 | echo "root:x:0:root" > /opt/etc/group 169 | die_on_error "Cannot create the group \"root\"!" 170 | 171 | export TERMINFO=/opt/share/terminfo 172 | export TEMP=/opt/tmp 173 | export TMP=/opt/tmp 174 | 175 | /opt/bin/opkg install wget ldconfig bash shadow logger 176 | cd "$OLD_PWD" || die "Cannot change the working directory to \"$OLD_PWD\"!" 177 | unset OLD_PWD 178 | ui_print "Entware has been installed. Please reboot the device!" 179 | fi 180 | 181 | unset ENTWARE_INSTALLATION_PATH ENTWARE ENTWARE_ARCH 182 | unset DNS1 DNS2 183 | --------------------------------------------------------------------------------