From: liaohua <liaoh...@huawei.com>

We have some questions about xz bcj filters.
1. Why ARM and ARM-Thumb bcj filters are little endian only?
2. Why there is no arm64 bcj filter? Are there any technical risks? Or other 
considerations?

It notes that ARM bcj filter is little endian only,
but we apply ARM bcj filter in big endian architecture(target: arm32 big 
endian, kernel and rootfs) and works ok too;
We only find that there are different code flows to parse “start=offset” option 
in source codes;

We add arm64 bcj filter support in local xz codes and it works ok.
We modify the Linux Kernel codes accordingly and use the new xz to compress 
kernel,
and kernel is decompressed successfully during startup.

The following is the patch for arm64 bcj filter support which is based on xz 
5.2.5 version.

Signed-off-by: liaohua <liaoh...@huawei.com>
---
 CMakeLists.txt                      |  3 ++
 configure.ac                        |  4 +--
 src/liblzma/api/lzma/bcj.h          |  4 +++
 src/liblzma/common/filter_common.c  | 10 +++++-
 src/liblzma/common/filter_decoder.c |  8 +++++
 src/liblzma/common/filter_encoder.c | 10 ++++++
 src/liblzma/simple/Makefile.inc     |  4 +++
 src/liblzma/simple/arm64.c          | 72 +++++++++++++++++++++++++++++++++++++
 src/liblzma/simple/simple_coder.h   |  7 ++++
 src/xz/args.c                       |  7 ++++
 src/xz/message.c                    |  5 ++-
 11 files changed, 130 insertions(+), 4 deletions(-)
 create mode 100644 src/liblzma/simple/arm64.c

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 34c6aca..f9d5db9 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -83,6 +83,7 @@ add_compile_definitions(
     HAVE_CHECK_SHA256
     HAVE_DECODERS
     HAVE_DECODER_ARM
+    HAVE_DECODER_ARM64
     HAVE_DECODER_ARMTHUMB
     HAVE_DECODER_DELTA
     HAVE_DECODER_IA64
@@ -93,6 +94,7 @@ add_compile_definitions(
     HAVE_DECODER_X86
     HAVE_ENCODERS
     HAVE_ENCODER_ARM
+    HAVE_ENCODER_ARM64
     HAVE_ENCODER_ARMTHUMB
     HAVE_ENCODER_DELTA
     HAVE_ENCODER_IA64
@@ -315,6 +317,7 @@ add_library(liblzma
     src/liblzma/rangecoder/range_decoder.h
     src/liblzma/rangecoder/range_encoder.h
     src/liblzma/simple/arm.c
+    src/liblzma/simple/arm64.c
     src/liblzma/simple/armthumb.c
     src/liblzma/simple/ia64.c
     src/liblzma/simple/powerpc.c
diff --git a/configure.ac b/configure.ac
index 5d288b9..3e51444 100644
--- a/configure.ac
+++ b/configure.ac
@@ -79,8 +79,8 @@ fi
 # Filters #
 ###########
 
-m4_define([SUPPORTED_FILTERS], 
[lzma1,lzma2,delta,x86,powerpc,ia64,arm,armthumb,sparc])dnl
-m4_define([SIMPLE_FILTERS], [x86,powerpc,ia64,arm,armthumb,sparc])
+m4_define([SUPPORTED_FILTERS], 
[lzma1,lzma2,delta,x86,powerpc,ia64,arm,arm64,armthumb,sparc])dnl
+m4_define([SIMPLE_FILTERS], [x86,powerpc,ia64,arm,arm64,armthumb,sparc])
 m4_define([LZ_FILTERS], [lzma1,lzma2])
 
 m4_foreach([NAME], [SUPPORTED_FILTERS],
diff --git a/src/liblzma/api/lzma/bcj.h b/src/liblzma/api/lzma/bcj.h
index 8e37538..d0a2094 100644
--- a/src/liblzma/api/lzma/bcj.h
+++ b/src/liblzma/api/lzma/bcj.h
@@ -49,6 +49,10 @@
         * Filter for SPARC binaries.
         */
 
+#define LZMA_FILTER_ARM64         LZMA_VLI_C(0x0a)
+       /**<
+        * Filter for ARM64 binaries.
+        */
 
 /**
  * \brief       Options for BCJ filters
diff --git a/src/liblzma/common/filter_common.c 
b/src/liblzma/common/filter_common.c
index 9ad5d5d..dea53e1 100644
--- a/src/liblzma/common/filter_common.c
+++ b/src/liblzma/common/filter_common.c
@@ -12,7 +12,6 @@
 
 #include "filter_common.h"
 
-
 static const struct {
        /// Filter ID
        lzma_vli id;
@@ -88,6 +87,15 @@ static const struct {
                .changes_size = false,
        },
 #endif
+#if defined(HAVE_ENCODER_ARM64) || defined(HAVE_DECODER_ARM64)
+       {
+               .id = LZMA_FILTER_ARM64,
+               .options_size = sizeof(lzma_options_bcj),
+               .non_last_ok = true,
+               .last_ok = false,
+               .changes_size = false,
+       },
+#endif
 #if defined(HAVE_ENCODER_ARMTHUMB) || defined(HAVE_DECODER_ARMTHUMB)
        {
                .id = LZMA_FILTER_ARMTHUMB,
diff --git a/src/liblzma/common/filter_decoder.c 
b/src/liblzma/common/filter_decoder.c
index c75b0a8..6d0f577 100644
--- a/src/liblzma/common/filter_decoder.c
+++ b/src/liblzma/common/filter_decoder.c
@@ -91,6 +91,14 @@ static const lzma_filter_decoder decoders[] = {
                .props_decode = &lzma_simple_props_decode,
        },
 #endif
+#ifdef HAVE_DECODER_ARM64
+       {
+               .id = LZMA_FILTER_ARM64,
+               .init = &lzma_simple_arm64_decoder_init,
+               .memusage = NULL,
+               .props_decode = &lzma_simple_props_decode,
+       },
+#endif
 #ifdef HAVE_DECODER_ARMTHUMB
        {
                .id = LZMA_FILTER_ARMTHUMB,
diff --git a/src/liblzma/common/filter_encoder.c 
b/src/liblzma/common/filter_encoder.c
index c5d8f39..4a9b747 100644
--- a/src/liblzma/common/filter_encoder.c
+++ b/src/liblzma/common/filter_encoder.c
@@ -116,6 +116,16 @@ static const lzma_filter_encoder encoders[] = {
                .props_encode = &lzma_simple_props_encode,
        },
 #endif
+#ifdef HAVE_ENCODER_ARM64
+       {
+               .id = LZMA_FILTER_ARM64,
+               .init = &lzma_simple_arm64_encoder_init,
+               .memusage = NULL,
+               .block_size = NULL,
+               .props_size_get = &lzma_simple_props_size,
+               .props_encode = &lzma_simple_props_encode,
+       },
+#endif
 #ifdef HAVE_ENCODER_ARMTHUMB
        {
                .id = LZMA_FILTER_ARMTHUMB,
diff --git a/src/liblzma/simple/Makefile.inc b/src/liblzma/simple/Makefile.inc
index 8a5e2d7..3e1f41d 100644
--- a/src/liblzma/simple/Makefile.inc
+++ b/src/liblzma/simple/Makefile.inc
@@ -38,6 +38,10 @@ if COND_FILTER_ARM
 liblzma_la_SOURCES += simple/arm.c
 endif
 
+if COND_FILTER_ARM64
+liblzma_la_SOURCES += simple/arm64.c
+endif
+
 if COND_FILTER_ARMTHUMB
 liblzma_la_SOURCES += simple/armthumb.c
 endif
diff --git a/src/liblzma/simple/arm64.c b/src/liblzma/simple/arm64.c
new file mode 100644
index 0000000..6147897
--- /dev/null
+++ b/src/liblzma/simple/arm64.c
@@ -0,0 +1,72 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       arm64.c
+/// \brief      Filter for ARM64 binaries
+///
+//  Authors:    Igor Pavlov
+//              Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "simple_private.h"
+
+
+static size_t
+arm64_code(void *simple lzma_attribute((__unused__)),
+               uint32_t now_pos, bool is_encoder,
+               uint8_t *buffer, size_t size)
+{
+       size_t i;
+       for (i = 0; i + 4 <= size; i += 4) {
+               // arm64 bl instruction: 0x94 and 0x97;
+               if (buffer[i + 3] == 0x94 || buffer[i + 3] == 0x97) {
+                       uint32_t src = ((uint32_t)(buffer[i + 2]) << 16)
+                                       | ((uint32_t)(buffer[i + 1]) << 8)
+                                       | (uint32_t)(buffer[i + 0]);
+                       src <<= 2;
+
+                       uint32_t dest;
+                       if (is_encoder)
+                               dest = now_pos + (uint32_t)(i) + src;
+                       else
+                               dest = src - (now_pos + (uint32_t)(i));
+
+                       dest >>= 2;
+                       buffer[i + 2] = (dest >> 16);
+                       buffer[i + 1] = (dest >> 8);
+                       buffer[i + 0] = dest;
+               }
+       }
+
+       return i;
+}
+
+
+static lzma_ret
+arm64_coder_init(lzma_next_coder *next, const lzma_allocator *allocator,
+               const lzma_filter_info *filters, bool is_encoder)
+{
+       return lzma_simple_coder_init(next, allocator, filters,
+                       &arm64_code, 0, 4, 4, is_encoder);
+}
+
+
+extern lzma_ret
+lzma_simple_arm64_encoder_init(lzma_next_coder *next,
+               const lzma_allocator *allocator,
+               const lzma_filter_info *filters)
+{
+       return arm64_coder_init(next, allocator, filters, true);
+}
+
+
+extern lzma_ret
+lzma_simple_arm64_decoder_init(lzma_next_coder *next,
+               const lzma_allocator *allocator,
+               const lzma_filter_info *filters)
+{
+       return arm64_coder_init(next, allocator, filters, false);
+}
diff --git a/src/liblzma/simple/simple_coder.h 
b/src/liblzma/simple/simple_coder.h
index 19c2ee0..4d150f6 100644
--- a/src/liblzma/simple/simple_coder.h
+++ b/src/liblzma/simple/simple_coder.h
@@ -51,6 +51,13 @@ extern lzma_ret lzma_simple_arm_decoder_init(lzma_next_coder 
*next,
                const lzma_allocator *allocator,
                const lzma_filter_info *filters);
 
+extern lzma_ret lzma_simple_arm64_encoder_init(lzma_next_coder *next,
+               const lzma_allocator *allocator,
+               const lzma_filter_info *filters);
+
+extern lzma_ret lzma_simple_arm64_decoder_init(lzma_next_coder *next,
+               const lzma_allocator *allocator,
+               const lzma_filter_info *filters);
 
 extern lzma_ret lzma_simple_armthumb_encoder_init(lzma_next_coder *next,
                const lzma_allocator *allocator,
diff --git a/src/xz/args.c b/src/xz/args.c
index 9238fb3..cf6a2d2 100644
--- a/src/xz/args.c
+++ b/src/xz/args.c
@@ -124,6 +124,7 @@ parse_real(args_info *args, int argc, char **argv)
                OPT_POWERPC,
                OPT_IA64,
                OPT_ARM,
+               OPT_ARM64,
                OPT_ARMTHUMB,
                OPT_SPARC,
                OPT_DELTA,
@@ -193,6 +194,7 @@ parse_real(args_info *args, int argc, char **argv)
                { "powerpc",      optional_argument, NULL,  OPT_POWERPC },
                { "ia64",         optional_argument, NULL,  OPT_IA64 },
                { "arm",          optional_argument, NULL,  OPT_ARM },
+               { "arm64",        optional_argument, NULL,  OPT_ARM64 },
                { "armthumb",     optional_argument, NULL,  OPT_ARMTHUMB },
                { "sparc",        optional_argument, NULL,  OPT_SPARC },
                { "delta",        optional_argument, NULL,  OPT_DELTA },
@@ -355,6 +357,11 @@ parse_real(args_info *args, int argc, char **argv)
                                        options_bcj(optarg));
                        break;
 
+               case OPT_ARM64:
+                       coder_add_filter(LZMA_FILTER_ARM64,
+                                       options_bcj(optarg));
+                       break;
+
                case OPT_ARMTHUMB:
                        coder_add_filter(LZMA_FILTER_ARMTHUMB,
                                        options_bcj(optarg));
diff --git a/src/xz/message.c b/src/xz/message.c
index aa915d2..069bcf9 100644
--- a/src/xz/message.c
+++ b/src/xz/message.c
@@ -1004,13 +1004,15 @@ message_filters_to_str(char buf[FILTERS_STR_SIZE],
                case LZMA_FILTER_POWERPC:
                case LZMA_FILTER_IA64:
                case LZMA_FILTER_ARM:
+               case LZMA_FILTER_ARM64:
                case LZMA_FILTER_ARMTHUMB:
                case LZMA_FILTER_SPARC: {
-                       static const char bcj_names[][9] = {
+                       static const char bcj_names[][10] = {
                                "x86",
                                "powerpc",
                                "ia64",
                                "arm",
+                               "arm64",
                                "armthumb",
                                "sparc",
                        };
@@ -1211,6 +1213,7 @@ message_help(bool long_help)
 "  --powerpc[=OPTS]    PowerPC BCJ filter (big endian only)\n"
 "  --ia64[=OPTS]       IA-64 (Itanium) BCJ filter\n"
 "  --arm[=OPTS]        ARM BCJ filter (little endian only)\n"
+"  --arm64[=OPTS]      ARM64 BCJ filter (little endian only)\n"
 "  --armthumb[=OPTS]   ARM-Thumb BCJ filter (little endian only)\n"
 "  --sparc[=OPTS]      SPARC BCJ filter\n"
 "                      Valid OPTS for all BCJ filters:\n"
-- 
2.12.3


Reply via email to