[Replicant] [vendor_replicant-scripts] [PATCH 9/9] add_adb_root: bootimages: Add support for xz compressed ramdisks

Denis 'GNUtoo' Carikli GNUtoo at cyberdimension.org
Fri Oct 1 17:47:59 UTC 2021


Since Linux 3.0.101 which is used in Replicant 6.0, the
kernel size increased a lot.

Because of that, in Replicant 11, the recovery initramfs is
compressed with xz to fit in the 8MiB RECOVERY partition of
the Galaxy SIII (GT-I9300) and Galaxy SIII 4G (GT-I9305).

Having the ability to add root to Replicant 11 recovery
images helps a lot with the development or configuration
of the recovery and install procedure as with this script
we can have a shell in the recovery (to look at partitions,
retrieve logs, etc) without needing to boot and setup
Replicant.

This script was also tested a Replicant 11 recovery on a
Galaxy SIII (GT-I9300), and once flashed the recovery boots
and we can get a shell with 'sudo adb shell'.

Signed-off-by: Denis 'GNUtoo' Carikli <GNUtoo at cyberdimension.org>
---
 images/add_adb_root/add_adb_root.py | 60 +++++++++++++++++++++++++----
 1 file changed, 52 insertions(+), 8 deletions(-)

diff --git a/images/add_adb_root/add_adb_root.py b/images/add_adb_root/add_adb_root.py
index 8dc6d34..4063576 100755
--- a/images/add_adb_root/add_adb_root.py
+++ b/images/add_adb_root/add_adb_root.py
@@ -14,6 +14,7 @@
 # You should have received a copy of the GNU Affero General Public License
 # along with this program.  If not, see <https://www.gnu.org/licenses/>.
 import enum
+import magic
 import os
 import re
 import sh
@@ -30,6 +31,7 @@ class ImageType(enum.Enum):
 class CompressionType(enum.Enum):
     none = 0
     gz = 1
+    xz = 2
 
 class Bootimage(object):
     def __init__(self, path):
@@ -39,7 +41,9 @@ class Bootimage(object):
         self._tmpdir = tempfile.mkdtemp()
 
         self._kernel = self._tmpdir + os.sep + "kernel.img"
-        self._ramdisk = self._tmpdir + os.sep + "ramdisk.cpio.gz"
+        # We don't know yet the compression type of the ramdisk so we use
+        # a generic .img instead of a specific extension like .gz or .xz
+        self._ramdisk = self._tmpdir + os.sep + "ramdisk.cpio.img"
         self._config = self._tmpdir + os.sep + "bootimg.cfg"
 
     def _get_metadata(self):
@@ -98,8 +102,8 @@ class Bootimage(object):
 
     def add_adb_root(self, output_file_path):
         self.extract()
-        self._ramdisk = Ramdisk(self._ramdisk,
-                                CompressionType.gz).add_adb_root()
+        compression = identify_compression_type(self._ramdisk)
+        self._ramdisk = Ramdisk(self._ramdisk, compression).add_adb_root()
         self.recreate(output_file_path)
 
         return output_file_path
@@ -208,14 +212,39 @@ class Ramdisk(object):
 
     def compress(self):
         if self._compression_type is not CompressionType.none:
-            sh.gzip("--no-name", self._path)
-            self._path = self._path + ".gz"
+            if self._compression_type == CompressionType.gz:
+                sh.gzip("--no-name", self._path)
+                self._path = self._path + ".gz"
+            elif self._compression_type == CompressionType.xz:
+                # TODO: also support other architectures than ARM
+                # See scripts/xz_wrap.sh in Linux source code for more details
+                sh.xz("--check=crc32", "--arm", "--lzma2=dict=32M", self._path)
+                self._path = self._path + ".xz"
+
         return self._path
 
     def uncompress(self):
-        if self._compression_type is not CompressionType.none:
-            sh.gunzip(self._path)
-            self._path = re.sub("\.gz$", "", self._path)
+        # The path looks like that: [...]/ramdisk.cpio.img. The .img is there
+        # because we needed to extract the file before finding out how it was
+        # compressed or if it was not compressed.
+        new_path = None
+        if self._compression_type == CompressionType.none:
+            new_path = re.sub("\.img$", "", self._path)
+        elif self._compression_type == CompressionType.gz:
+            new_path = re.sub("\.img$", ".gz", self._path)
+        elif self._compression_type == CompressionType.xz:
+            new_path = re.sub("\.img$", ".xz", self._path)
+
+        os.rename(self._path, new_path)
+        self._path = new_path
+
+        if self._compression_type == CompressionType.gz:
+                sh.gunzip(self._path)
+                self._path = re.sub("\.gz$", "", self._path)
+        elif self._compression_type == CompressionType.xz:
+                sh.unxz(self._path)
+                self._path = re.sub("\.xz$", "", self._path)
+
         return self._path
 
     def add_adb_root(self):
@@ -237,6 +266,21 @@ def usage(progname):
         progname))
     sys.exit(1)
 
+def identify_compression_type(path):
+    m = magic.detect_from_filename(path)
+    if not m:
+        print("/!\ MIME type not found for {}".format(path))
+        sys.exit(1)
+    mime_type = m.mime_type
+    if mime_type == 'application/gzip':
+        return CompressionType.gz
+    elif mime_type == 'application/x-xz':
+        return CompressionType.xz
+    else:
+        print("/!\ TODO: MIME type {} (of file {}) is not implemented".format(
+            m.mime_type, path))
+        sys.exit(1)
+
 def identify_image_type(path):
     try:
         output = sh.abootimg("-i", path)
-- 
2.33.0



More information about the Replicant mailing list