diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 6fe314c..3e52760 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -28,7 +28,7 @@ jobs: - name: Set up JDK uses: actions/setup-java@v1 with: - java-version: 11 + java-version: 17 - name: apt run: sudo apt install device-tree-compiler p7zip-full @@ -53,7 +53,7 @@ jobs: - name: Set up JDK uses: actions/setup-java@v1 with: - java-version: 11 + java-version: 17 - name: brew run: brew install dtc @@ -76,7 +76,7 @@ jobs: - name: Set up JDK uses: actions/setup-java@v1 with: - java-version: 11 + java-version: 17 - name: Set up Python uses: actions/setup-python@v2 diff --git a/README.md b/README.md index 224ece1..0ac8e21 100644 --- a/README.md +++ b/README.md @@ -8,16 +8,16 @@ A tool for reverse engineering Android ROM images. #### install required packages -Linux: `sudo apt install git device-tree-compiler lz4 xz-utils zlib1g-dev openjdk-11-jdk gcc g++ python3 python-is-python3 p7zip-full` +Linux: `sudo apt install git device-tree-compiler lz4 xz-utils zlib1g-dev openjdk-17-jdk gcc g++ python3 python-is-python3 p7zip-full` Mac: `brew install lz4 xz dtc` -Mac: Make sure you have `JDK9+` properly installed. +Mac: Make sure you have `JDK9+` properly installed. JDK 17 is recommended. -Windows Subsystem for Linux(WSL): `sudo apt install git device-tree-compiler lz4 xz-utils zlib1g-dev openjdk-11-jdk gcc g++ python` +Windows Subsystem for Linux(WSL): `sudo apt install git device-tree-compiler lz4 xz-utils zlib1g-dev openjdk-17-jdk gcc g++ python` Windows: Make sure you have `python3`, `JDK9+` and `openssl` properly installed. -An easy way is to install [Anaconda](https://www.anaconda.com/products/individual#windows) and [Oracle JDK 11](https://www.oracle.com/java/technologies/javase-jdk11-downloads.html), then run the program under anaconda PowerShell. +An easy way is to install [Anaconda](https://www.anaconda.com/products/individual#windows) and [Oracle JDK 17](https://www.oracle.com/java/technologies/downloads/#java17), then run the program under anaconda PowerShell. Or install them with chocolate: `choco install openssl dtc-msys2` #### Parsing and packing @@ -95,11 +95,12 @@ This will enable c++ modules, which is necessary for working with sparse images. | TS10 | Topway | Y | 10 | car headunit, @mariodantas | | Pixel XL (marlin) | HTC | Y | 9.0.0 (PPR2.180905.006,
Sep 2018)| [more ...](doc/additional_tricks.md#pixel-xl-marlin) | | K3 (CPH1955) | OPPO | Y for recovery.img
N for boot.img | Pie | [more](doc/additional_tricks.md#k3-cph1955) | -| Z18 (NX606J) | ZTE | Y | 8.1.0 | [more...](doc/additional_tricks.md#nx606j) | +| Z18 (NX606J) | ZTE | Y | 8.1.0 | [more...](doc/additional_tricks.md#nx606j) | | Nexus 9 (volantis/flounder) | HTC | Y(with some tricks) | 7.1.1 (N9F27M, Oct 2017) | [tricks](doc/additional_tricks.md#tricks-for-nexus-9volantis)| | Nexus 5x (bullhead) | LG | Y | 6.0.0_r12 (MDA89E) | | | Moto X (2013) T-Mobile | Motorola | N | | | | X7 (PD1602_A_3.12.8) | VIVO | N | ? | [Issue 35](https://github.com/cfig/Android_boot_image_editor/issues/35) | +| Realme GT Neo 3 | Realme | N | 12 | [Issue 105](https://github.com/cfig/Android_boot_image_editor/issues/105) | ## more examples
diff --git a/aosp/avb/avbtool.v1.2.py b/aosp/avb/avbtool.v1.2.py index f944af4..67416d4 100755 --- a/aosp/avb/avbtool.v1.2.py +++ b/aosp/avb/avbtool.v1.2.py @@ -930,18 +930,22 @@ class ImageHandler(object): struct.calcsize(ImageChunk.FORMAT))) self._read_header() - def append_raw(self, data): + def append_raw(self, data, multiple_block_size=True): """Appends a RAW chunk to the sparse file. - The length of the given data must be a multiple of the block size. + The length of the given data must be a multiple of the block size, + unless |multiple_block_size| is False. Arguments: data: Data to append as bytes. + multiple_block_size: whether to check the length of the + data is a multiple of the block size. Raises: OSError: If ImageHandler was initialized in read-only mode. """ - assert len(data) % self.block_size == 0 + if multiple_block_size: + assert len(data) % self.block_size == 0 if self._read_only: raise OSError('ImageHandler is in read-only mode.') @@ -3684,7 +3688,12 @@ class Avb(object): # Ensure image is multiple of block_size. rounded_image_size = round_to_multiple(image.image_size, block_size) if rounded_image_size > image.image_size: - image.append_raw('\0' * (rounded_image_size - image.image_size)) + # If we need to round up the image size, it means the length of the + # data to append is not a multiple of block size. + # Setting multiple_block_size to false, so append_raw() will not + # require it. + image.append_raw(b'\0' * (rounded_image_size - image.image_size), + multiple_block_size=False) # If image size exceeds the maximum image size, fail. if partition_size > 0: @@ -3753,7 +3762,8 @@ class Avb(object): padding_needed = (round_to_multiple(len(hash_tree), image.block_size) - len(hash_tree)) hash_tree_with_padding = hash_tree + b'\0' * padding_needed - image.append_raw(hash_tree_with_padding) + if len(hash_tree_with_padding) > 0: + image.append_raw(hash_tree_with_padding) len_hashtree_and_fec = len(hash_tree_with_padding) # Generate FEC codes, if requested. diff --git a/aosp/avb/data/testkey_rsa4096_pub.bin b/aosp/avb/data/testkey_rsa4096_pub.bin new file mode 100644 index 0000000..f2e8fbd Binary files /dev/null and b/aosp/avb/data/testkey_rsa4096_pub.bin differ diff --git a/aosp/avb/data/testkey_rsa4096_pub.pem b/aosp/avb/data/testkey_rsa4096_pub.pem new file mode 100644 index 0000000..efd7144 --- /dev/null +++ b/aosp/avb/data/testkey_rsa4096_pub.pem @@ -0,0 +1,14 @@ +-----BEGIN PUBLIC KEY----- +MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA2ASv49OEbH4NiT3CjNMS +VeliyfEPXswWcqtEfCxlSpS1FisAuwbvEwdTTPlkuSh6G4SYiNhnpCP5p0vcSg/3 +OhiuVKgV/rCtrDXaO60nvK/o0y83NNZRK2xaJ9eWBq9ruIDK+jC0sYWzTaqqwxY0 +Grjnx/r5CXerl5PrRK7PILzwgBHbIwxHcblt1ntgR4cWVpO3wiqasEwBDDDYk4fw +7W6LvjBb9qav3YB8RV6PkZNeRP64ggfuecq/MXNiWOPNxLzCER2hSr/+J32h9jWj +XsrcVy8+8Mldhmr4r2an7c247aFfupuFGtUJrpROO8/LXMl5gPfMpkqoatjTMRH5 +9gJjKhot0RpmGxZBvb33TcBK5SdJX39Y4yct5clmDlI4Fjj7FutTP+b96aJeJVnY +eUX/A0wmogBajsJRoRX5e/RcgZsYRzXYLQXprQ81dBWjjovMJ9p8XeT6BNMFC7o6 +sklFL0fHDUE/l4BNP8G1u3BfpzevSCISRS71D4eS4oQB+RIPFBUkzomZ7rnEF3Bw +Feq+xmwfYrP0LRaH+1YeRauuMuReke1TZl697a3mEjkNg8noa2wtpe7EWmaujJfX +DWxJx/XEkjGLCe4z2qk3tkkY+A5gRcgzke8gVxC+eC2DJtbKYfkv4L8FMFJaEhwA +p13MfC7FlYujO/BDLl7dANsCAwEAAQ== +-----END PUBLIC KEY----- diff --git a/aosp/libavb.diff b/aosp/libavb.diff deleted file mode 100644 index 5dddbd0..0000000 --- a/aosp/libavb.diff +++ /dev/null @@ -1,16 +0,0 @@ -diff --git a/aosp/libavb/src/avb/c/avb_sysdeps_posix.c b/aosp/libavb/src/avb/c/avb_sysdeps_posix.c -index e26c3ef..f1572a5 100644 ---- a/aosp/libavb/src/avb/c/avb_sysdeps_posix.c -+++ b/aosp/libavb/src/avb/c/avb_sysdeps_posix.c -@@ -22,7 +22,11 @@ - * SOFTWARE. - */ - -+#if defined(__APPLE__) && defined(__MACH__) -+#include -+#else - #include -+#endif - #include - #include - #include diff --git a/aosp/libavb1.2/build.gradle b/aosp/libavb1.2/build.gradle index 3c5abcc..41c9e4d 100644 --- a/aosp/libavb1.2/build.gradle +++ b/aosp/libavb1.2/build.gradle @@ -1,5 +1,4 @@ apply plugin: "c" -apply plugin: "cpp" model { buildTypes { diff --git a/aosp/libavb1.2/src/avb/c/avb_cmdline.c b/aosp/libavb1.2/src/avb/c/avb_cmdline.c index 5773a20..6613020 100644 --- a/aosp/libavb1.2/src/avb/c/avb_cmdline.c +++ b/aosp/libavb1.2/src/avb/c/avb_cmdline.c @@ -353,6 +353,10 @@ AvbSlotVerifyResult avb_append_options( // remapped by avb_manage_hashtree_error_mode(). avb_assert_not_reached(); break; + case AVB_HASHTREE_ERROR_MODE_PANIC: + verity_mode = "panicking"; + dm_verity_mode = "panic_on_corruption"; + break; } new_ret = avb_replace( slot_data->cmdline, "$(ANDROID_VERITY_MODE)", dm_verity_mode); diff --git a/aosp/libavb1.2/src/avb/c/avb_crc32.c b/aosp/libavb1.2/src/avb/c/avb_crc32.c index 7d4cb09..6b70383 100644 --- a/aosp/libavb1.2/src/avb/c/avb_crc32.c +++ b/aosp/libavb1.2/src/avb/c/avb_crc32.c @@ -1,114 +1,66 @@ -/*- - * COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or - * code or tables extracted from it, as desired without restriction. - */ - /* - * First, the polynomial itself and its table of feedback terms. The - * polynomial is - * X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0 - * - * Note that we take it "backwards" and put the highest-order term in - * the lowest-order bit. The X^32 term is "implied"; the LSB is the - * X^31 term, etc. The X^0 term (usually shown as "+1") results in - * the MSB being 1 - * - * Note that the usual hardware shift register implementation, which - * is what we're using (we're merely optimizing it by doing eight-bit - * chunks at a time) shifts bits into the lowest-order term. In our - * implementation, that means shifting towards the right. Why do we - * do it this way? Because the calculated CRC must be transmitted in - * order from highest-order term to lowest-order term. UARTs transmit - * characters in order from LSB to MSB. By storing the CRC this way - * we hand it to the UART in the order low-byte to high-byte; the UART - * sends each low-bit to hight-bit; and the result is transmission bit - * by bit from highest- to lowest-order term without requiring any bit - * shuffling on our part. Reception works similarly + * Copyright 2020 The Android Open Source Project * - * The feedback terms table consists of 256, 32-bit entries. Notes + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * The table can be generated at runtime if desired; code to do so - * is shown later. It might not be obvious, but the feedback - * terms simply represent the results of eight shift/xor opera - * tions for all combinations of data and CRC register values - * - * The values must be right-shifted by eight bits by the "updcrc - * logic; the shift must be unsigned (bring in zeroes). On some - * hardware you could probably optimize the shift in assembler by - * using byte-swap instructions - * polynomial $edb88320 + * http://www.apache.org/licenses/LICENSE-2.0 * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* See https://en.wikipedia.org/wiki/Computation_of_cyclic_redundancy_checks + * for info on the general algorithm. We use the following configuration: + * 32-bit CRC + * Polynomial = 0x04C11DB7 + * MSB-first + * Input and output complement + * Input and output bit reversal * - * CRC32 code derived from work by Gary S. Brown. + * This implementation optimizes for size and readability. We only need this for + * 28 bytes of A/B booting metadata, so efficiency is largely irrelevant whereas + * a 1KiB lookup table can be a significant cost for bootloaders. */ -#include "avb_sysdeps.h" #include "avb_util.h" -/* Code taken from FreeBSD 8 */ +/* Lookup table for reversing 4 bits. */ +/* clang-format off */ +static uint8_t reverse_4bit_table[] = { + 0x0, 0x8, 0x4, 0xC, + 0x2, 0xA, 0x6, 0xE, + 0x1, 0x9, 0x5, 0xD, + 0x3, 0xB, 0x7, 0xF +}; +/* clang-format on */ -static uint32_t iavb_crc32_tab[] = { - 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, - 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, - 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, - 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, - 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, - 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, - 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, - 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, - 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, - 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, - 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, - 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, - 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, - 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, - 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, - 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, - 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, - 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, - 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, - 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, - 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, - 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, - 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, - 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, - 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, - 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, - 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, - 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, - 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, - 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, - 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, - 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, - 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, - 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, - 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, - 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, - 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, - 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, - 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, - 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, - 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, - 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, - 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d}; - -/* - * A function that calculates the CRC-32 based on the table above is - * given below for documentation purposes. An equivalent implementation - * of this function that's actually used in the kernel can be found - * in sys/libkern.h, where it can be inlined. - */ - -static uint32_t iavb_crc32(uint32_t crc_in, const uint8_t* buf, int size) { - const uint8_t* p = buf; - uint32_t crc; +static uint8_t reverse_byte(uint8_t val) { + return (reverse_4bit_table[val & 0xF] << 4) | reverse_4bit_table[val >> 4]; +} - crc = crc_in ^ ~0U; - while (size--) - crc = iavb_crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8); - return crc ^ ~0U; +static uint32_t reverse_uint32(uint32_t val) { + return (reverse_byte(val) << 24) | (reverse_byte(val >> 8) << 16) | + (reverse_byte(val >> 16) << 8) | reverse_byte(val >> 24); } uint32_t avb_crc32(const uint8_t* buf, size_t size) { - return iavb_crc32(0, buf, size); + uint32_t crc = 0xFFFFFFFF; + + for (size_t i = 0; i < size; ++i) { + crc = crc ^ ((uint32_t)reverse_byte(buf[i]) << 24); + for (int j = 0; j < 8; ++j) { + if (crc & 0x80000000) { + crc = (crc << 1) ^ 0x04C11DB7; + } else { + crc <<= 1; + } + } + } + + return reverse_uint32(~crc); } diff --git a/aosp/libavb1.2/src/avb/c/avb_descriptor.c b/aosp/libavb1.2/src/avb/c/avb_descriptor.c index cfc2aac..9a5a482 100644 --- a/aosp/libavb1.2/src/avb/c/avb_descriptor.c +++ b/aosp/libavb1.2/src/avb/c/avb_descriptor.c @@ -48,6 +48,8 @@ bool avb_descriptor_foreach(const uint8_t* image_data, const uint8_t* desc_start; const uint8_t* desc_end; const uint8_t* p; + uint64_t desc_offset = 0; + uint64_t desc_size = 0; if (image_data == NULL) { avb_error("image_data is NULL\n."); @@ -59,6 +61,9 @@ bool avb_descriptor_foreach(const uint8_t* image_data, goto out; } + /* The data is supposed to have been cryptographically verified at this point, + * This check is just adding defense in depth. + */ if (image_size < sizeof(AvbVBMetaImageHeader)) { avb_error("Length is smaller than header.\n"); goto out; @@ -75,23 +80,53 @@ bool avb_descriptor_foreach(const uint8_t* image_data, header = (const AvbVBMetaImageHeader*)image_data; image_end = image_data + image_size; - desc_start = image_data + sizeof(AvbVBMetaImageHeader) + - avb_be64toh(header->authentication_data_block_size) + - avb_be64toh(header->descriptors_offset); + /* Since the data is supposed to have been cryptographically verified at this + * point, being overflow-safe is just for defense. + * The following lines are overflow-safe version of: + * desc_offset = sizeof(AvbVBMetaImageHeader) + + * avb_be64toh(header->authentication_data_block_size)) + + * avb_be64toh(header->descriptors_offset) + */ + if (!avb_safe_add(&desc_offset, + sizeof(AvbVBMetaImageHeader), + avb_be64toh(header->authentication_data_block_size))) { + avb_error("Invalid authentication data block size.\n"); + goto out; + } + if (!avb_safe_add_to(&desc_offset, avb_be64toh(header->descriptors_offset))) { + avb_error("Invalid descriptors offset.\n"); + goto out; + } + + if (desc_offset > (uint64_t)(image_end - image_data)) { + avb_error("Descriptors not inside passed-in data.\n"); + goto out; + } - desc_end = desc_start + avb_be64toh(header->descriptors_size); + desc_start = image_data + desc_offset; - if (desc_start < image_data || desc_start > image_end || - desc_end < image_data || desc_end > image_end || desc_end < desc_start) { + desc_size = avb_be64toh(header->descriptors_size); + if (desc_size > (uint64_t)(image_end - desc_start)) { avb_error("Descriptors not inside passed-in data.\n"); goto out; } + desc_end = desc_start + desc_size; + for (p = desc_start; p < desc_end;) { - const AvbDescriptor* dh = (const AvbDescriptor*)p; - avb_assert_aligned(dh); - uint64_t nb_following = avb_be64toh(dh->num_bytes_following); + uint64_t nb_following; uint64_t nb_total = 0; + const AvbDescriptor* dh; + + if (sizeof(AvbDescriptor) > (size_t)(desc_end - p)) { + avb_error("Invalid descriptor length.\n"); + goto out; + } + + dh = (const AvbDescriptor*)p; + avb_assert_aligned(dh); + nb_following = avb_be64toh(dh->num_bytes_following); + if (!avb_safe_add(&nb_total, sizeof(AvbDescriptor), nb_following)) { avb_error("Invalid descriptor length.\n"); goto out; @@ -102,7 +137,7 @@ bool avb_descriptor_foreach(const uint8_t* image_data, goto out; } - if (nb_total + p < desc_start || nb_total + p > desc_end) { + if (nb_total > (uint64_t)(desc_end - p)) { avb_error("Invalid data in descriptors array.\n"); goto out; } @@ -111,10 +146,7 @@ bool avb_descriptor_foreach(const uint8_t* image_data, goto out; } - if (!avb_safe_add_to((uint64_t*)(&p), nb_total)) { - avb_error("Invalid descriptor length.\n"); - goto out; - } + p += nb_total; } ret = true; diff --git a/aosp/libavb1.2/src/avb/c/avb_slot_verify.c b/aosp/libavb1.2/src/avb/c/avb_slot_verify.c index fc4c564..8e0721d 100644 --- a/aosp/libavb1.2/src/avb/c/avb_slot_verify.c +++ b/aosp/libavb1.2/src/avb/c/avb_slot_verify.c @@ -468,6 +468,7 @@ out: loaded_partition->data_size = image_size; loaded_partition->data = image_buf; loaded_partition->preloaded = image_preloaded; + loaded_partition->verify_result = ret; image_buf = NULL; } @@ -1335,7 +1336,7 @@ out: static bool has_system_partition(AvbOps* ops, const char* ab_suffix) { char part_name[AVB_PART_NAME_MAX_SIZE]; - char* system_part_name = "system"; + const char* system_part_name = "system"; char guid_buf[37]; AvbIOResult io_ret; @@ -1706,7 +1707,7 @@ const char* avb_slot_verify_result_to_string(AvbSlotVerifyResult result) { return ret; } -void avb_slot_verify_data_calculate_vbmeta_digest(AvbSlotVerifyData* data, +void avb_slot_verify_data_calculate_vbmeta_digest(const AvbSlotVerifyData* data, AvbDigestType digest_type, uint8_t* out_digest) { bool ret = false; diff --git a/aosp/libavb1.2/src/avb/c/avb_sysdeps_posix.c b/aosp/libavb1.2/src/avb/c/avb_sysdeps_posix.c index f1572a5..e26c3ef 100644 --- a/aosp/libavb1.2/src/avb/c/avb_sysdeps_posix.c +++ b/aosp/libavb1.2/src/avb/c/avb_sysdeps_posix.c @@ -22,11 +22,7 @@ * SOFTWARE. */ -#if defined(__APPLE__) && defined(__MACH__) -#include -#else #include -#endif #include #include #include diff --git a/aosp/libavb1.2/src/avb/c/avb_sha256.c b/aosp/libavb1.2/src/avb/c/sha256_impl.c similarity index 93% rename from aosp/libavb1.2/src/avb/c/avb_sha256.c rename to aosp/libavb1.2/src/avb/c/sha256_impl.c index 8a1c3ae..4a3dba1 100644 --- a/aosp/libavb1.2/src/avb/c/avb_sha256.c +++ b/aosp/libavb1.2/src/avb/c/sha256_impl.c @@ -36,6 +36,7 @@ */ #include "avb_sha.h" +#include "avb_crypto_ops_impl.h" #define SHFR(x, n) (x >> n) #define ROTR(x, n) ((x >> n) | (x << ((sizeof(x) << 3) - n))) @@ -112,7 +113,8 @@ static const uint32_t sha256_k[64] = { 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2}; /* SHA-256 implementation */ -void avb_sha256_init(AvbSHA256Ctx* ctx) { +void avb_sha256_init(AvbSHA256Ctx* avb_ctx) { + AvbSHA256ImplCtx* ctx = (AvbSHA256ImplCtx*)avb_ctx->reserved; #ifndef UNROLL_LOOPS int i; for (i = 0; i < 8; i++) { @@ -133,7 +135,7 @@ void avb_sha256_init(AvbSHA256Ctx* ctx) { ctx->tot_len = 0; } -static void SHA256_transform(AvbSHA256Ctx* ctx, +static void SHA256_transform(AvbSHA256ImplCtx* ctx, const uint8_t* message, size_t block_nb) { uint32_t w[64]; @@ -332,7 +334,8 @@ static void SHA256_transform(AvbSHA256Ctx* ctx, } } -void avb_sha256_update(AvbSHA256Ctx* ctx, const uint8_t* data, size_t len) { +void avb_sha256_update(AvbSHA256Ctx* avb_ctx, const uint8_t* data, size_t len) { + AvbSHA256ImplCtx* ctx = (AvbSHA256ImplCtx*)avb_ctx->reserved; size_t block_nb; size_t new_len, rem_len, tmp_len; const uint8_t* shifted_data; @@ -363,7 +366,8 @@ void avb_sha256_update(AvbSHA256Ctx* ctx, const uint8_t* data, size_t len) { ctx->tot_len += (block_nb + 1) << 6; } -uint8_t* avb_sha256_final(AvbSHA256Ctx* ctx) { +uint8_t* avb_sha256_final(AvbSHA256Ctx* avb_ctx) { + AvbSHA256ImplCtx* ctx = (AvbSHA256ImplCtx*)avb_ctx->reserved; size_t block_nb; size_t pm_len; uint64_t len_b; @@ -385,18 +389,18 @@ uint8_t* avb_sha256_final(AvbSHA256Ctx* ctx) { #ifndef UNROLL_LOOPS for (i = 0; i < 8; i++) { - UNPACK32(ctx->h[i], &ctx->buf[i << 2]); + UNPACK32(ctx->h[i], &avb_ctx->buf[i << 2]); } #else - UNPACK32(ctx->h[0], &ctx->buf[0]); - UNPACK32(ctx->h[1], &ctx->buf[4]); - UNPACK32(ctx->h[2], &ctx->buf[8]); - UNPACK32(ctx->h[3], &ctx->buf[12]); - UNPACK32(ctx->h[4], &ctx->buf[16]); - UNPACK32(ctx->h[5], &ctx->buf[20]); - UNPACK32(ctx->h[6], &ctx->buf[24]); - UNPACK32(ctx->h[7], &ctx->buf[28]); + UNPACK32(ctx->h[0], &avb_ctx->buf[0]); + UNPACK32(ctx->h[1], &avb_ctx->buf[4]); + UNPACK32(ctx->h[2], &avb_ctx->buf[8]); + UNPACK32(ctx->h[3], &avb_ctx->buf[12]); + UNPACK32(ctx->h[4], &avb_ctx->buf[16]); + UNPACK32(ctx->h[5], &avb_ctx->buf[20]); + UNPACK32(ctx->h[6], &avb_ctx->buf[24]); + UNPACK32(ctx->h[7], &avb_ctx->buf[28]); #endif /* !UNROLL_LOOPS */ - return ctx->buf; + return avb_ctx->buf; } diff --git a/aosp/libavb1.2/src/avb/c/avb_sha512.c b/aosp/libavb1.2/src/avb/c/sha512_impl.c similarity index 93% rename from aosp/libavb1.2/src/avb/c/avb_sha512.c rename to aosp/libavb1.2/src/avb/c/sha512_impl.c index 6cdc494..3d66a53 100644 --- a/aosp/libavb1.2/src/avb/c/avb_sha512.c +++ b/aosp/libavb1.2/src/avb/c/sha512_impl.c @@ -36,6 +36,7 @@ */ #include "avb_sha.h" +#include "avb_crypto_ops_impl.h" #define SHFR(x, n) (x >> n) #define ROTR(x, n) ((x >> n) | (x << ((sizeof(x) << 3) - n))) @@ -131,7 +132,8 @@ static const uint64_t sha512_k[80] = { /* SHA-512 implementation */ -void avb_sha512_init(AvbSHA512Ctx* ctx) { +void avb_sha512_init(AvbSHA512Ctx* avb_ctx) { + AvbSHA512ImplCtx* ctx = (AvbSHA512ImplCtx*)avb_ctx->reserved; #ifdef UNROLL_LOOPS_SHA512 ctx->h[0] = sha512_h0[0]; ctx->h[1] = sha512_h0[1]; @@ -152,7 +154,7 @@ void avb_sha512_init(AvbSHA512Ctx* ctx) { ctx->tot_len = 0; } -static void SHA512_transform(AvbSHA512Ctx* ctx, +static void SHA512_transform(AvbSHA512ImplCtx* ctx, const uint8_t* message, size_t block_nb) { uint64_t w[80]; @@ -318,7 +320,8 @@ static void SHA512_transform(AvbSHA512Ctx* ctx, } } -void avb_sha512_update(AvbSHA512Ctx* ctx, const uint8_t* data, size_t len) { +void avb_sha512_update(AvbSHA512Ctx* avb_ctx, const uint8_t* data, size_t len) { + AvbSHA512ImplCtx* ctx = (AvbSHA512ImplCtx*)avb_ctx->reserved; size_t block_nb; size_t new_len, rem_len, tmp_len; const uint8_t* shifted_data; @@ -349,7 +352,8 @@ void avb_sha512_update(AvbSHA512Ctx* ctx, const uint8_t* data, size_t len) { ctx->tot_len += (block_nb + 1) << 7; } -uint8_t* avb_sha512_final(AvbSHA512Ctx* ctx) { +uint8_t* avb_sha512_final(AvbSHA512Ctx* avb_ctx) { + AvbSHA512ImplCtx* ctx = (AvbSHA512ImplCtx*)avb_ctx->reserved; size_t block_nb; size_t pm_len; uint64_t len_b; @@ -371,18 +375,18 @@ uint8_t* avb_sha512_final(AvbSHA512Ctx* ctx) { SHA512_transform(ctx, ctx->block, block_nb); #ifdef UNROLL_LOOPS_SHA512 - UNPACK64(ctx->h[0], &ctx->buf[0]); - UNPACK64(ctx->h[1], &ctx->buf[8]); - UNPACK64(ctx->h[2], &ctx->buf[16]); - UNPACK64(ctx->h[3], &ctx->buf[24]); - UNPACK64(ctx->h[4], &ctx->buf[32]); - UNPACK64(ctx->h[5], &ctx->buf[40]); - UNPACK64(ctx->h[6], &ctx->buf[48]); - UNPACK64(ctx->h[7], &ctx->buf[56]); + UNPACK64(ctx->h[0], &avb_ctx->buf[0]); + UNPACK64(ctx->h[1], &avb_ctx->buf[8]); + UNPACK64(ctx->h[2], &avb_ctx->buf[16]); + UNPACK64(ctx->h[3], &avb_ctx->buf[24]); + UNPACK64(ctx->h[4], &avb_ctx->buf[32]); + UNPACK64(ctx->h[5], &avb_ctx->buf[40]); + UNPACK64(ctx->h[6], &avb_ctx->buf[48]); + UNPACK64(ctx->h[7], &avb_ctx->buf[56]); #else for (i = 0; i < 8; i++) - UNPACK64(ctx->h[i], &ctx->buf[i << 3]); + UNPACK64(ctx->h[i], &avb_ctx->buf[i << 3]); #endif /* UNROLL_LOOPS_SHA512 */ - return ctx->buf; + return avb_ctx->buf; } diff --git a/aosp/libavb1.2/src/avb/headers/avb_crypto_ops_impl.h b/aosp/libavb1.2/src/avb/headers/avb_crypto_ops_impl.h new file mode 100644 index 0000000..675aa5b --- /dev/null +++ b/aosp/libavb1.2/src/avb/headers/avb_crypto_ops_impl.h @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifdef AVB_INSIDE_LIBAVB_H +#error "You can't include avb_crypto_ops_impl.h in the public header libavb.h." +#endif + +#ifndef AVB_COMPILATION +#error "Never include this file, it may only be used from internal avb code." +#endif + +#ifndef AVB_CRYPTO_OPS_IMPL_H_ +#define AVB_CRYPTO_OPS_IMPL_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "avb_sysdeps.h" + +/* Block size in bytes of a SHA-256 digest. */ +#define AVB_SHA256_BLOCK_SIZE 64 + +/* Block size in bytes of a SHA-512 digest. */ +#define AVB_SHA512_BLOCK_SIZE 128 + +/* Data structure used for SHA-256. */ +typedef struct { + uint32_t h[8]; + uint64_t tot_len; + size_t len; + uint8_t block[2 * AVB_SHA256_BLOCK_SIZE]; +} AvbSHA256ImplCtx; + +/* Data structure used for SHA-512. */ +typedef struct { + uint64_t h[8]; + uint64_t tot_len; + size_t len; + uint8_t block[2 * AVB_SHA512_BLOCK_SIZE]; +} AvbSHA512ImplCtx; + +#define AVB_SHA256_CONTEXT_SIZE sizeof(AvbSHA256ImplCtx) +#define AVB_SHA512_CONTEXT_SIZE sizeof(AvbSHA512ImplCtx) + +#ifdef __cplusplus +} +#endif + +#endif /* AVB_CRYPTO_OPS_IMPL_H_ */ diff --git a/aosp/libavb1.2/src/avb/headers/avb_hashtree_descriptor.h b/aosp/libavb1.2/src/avb/headers/avb_hashtree_descriptor.h index d0f7e2c..6595f46 100644 --- a/aosp/libavb1.2/src/avb/headers/avb_hashtree_descriptor.h +++ b/aosp/libavb1.2/src/avb/headers/avb_hashtree_descriptor.h @@ -40,9 +40,12 @@ extern "C" { * AVB_HASHTREE_DESCRIPTOR_FLAGS_DO_NOT_USE_AB: Do not apply the default A/B * partition logic to this partition. This is intentionally a negative boolean * because A/B should be both the default and most used in practice. + * AVB_HASHTREE_DESCRIPTOR_FLAGS_CHECK_AT_MOST_ONCE: supports to validate hashes + * at most once in DM-Verity. */ typedef enum { AVB_HASHTREE_DESCRIPTOR_FLAGS_DO_NOT_USE_AB = (1 << 0), + AVB_HASHTREE_DESCRIPTOR_FLAGS_CHECK_AT_MOST_ONCE = (1 << 1), } AvbHashtreeDescriptorFlags; /* A descriptor containing information about a dm-verity hashtree. diff --git a/aosp/libavb1.2/src/avb/headers/avb_sha.h b/aosp/libavb1.2/src/avb/headers/avb_sha.h index 82ac9a5..f4c42ea 100644 --- a/aosp/libavb1.2/src/avb/headers/avb_sha.h +++ b/aosp/libavb1.2/src/avb/headers/avb_sha.h @@ -40,28 +40,28 @@ extern "C" { #include "avb_crypto.h" #include "avb_sysdeps.h" -/* Block size in bytes of a SHA-256 digest. */ -#define AVB_SHA256_BLOCK_SIZE 64 - - -/* Block size in bytes of a SHA-512 digest. */ -#define AVB_SHA512_BLOCK_SIZE 128 +/* The following defines must be set to something appropriate + * + * AVB_SHA256_CONTEXT_SIZE - the size of AvbSHA256Ctx, excluding the buffer + * AVB_SHA512_CONTEXT_SIZE - the size of AvbSHA512Ctx, exclusing the buffer + * + * For example, if AvbSHA512Ctx is implemented using BoringSSL this would be + * defined as sizeof(SHA256_CTX). + * + * We expect the implementation to provide a header file with the name + * avb_crypto_ops_impl.h to do all this. + */ +#include "avb_crypto_ops_impl.h" /* Data structure used for SHA-256. */ typedef struct { - uint32_t h[8]; - uint64_t tot_len; - size_t len; - uint8_t block[2 * AVB_SHA256_BLOCK_SIZE]; + uint8_t reserved[AVB_SHA256_CONTEXT_SIZE]; uint8_t buf[AVB_SHA256_DIGEST_SIZE]; /* Used for storing the final digest. */ } AvbSHA256Ctx; /* Data structure used for SHA-512. */ typedef struct { - uint64_t h[8]; - uint64_t tot_len; - size_t len; - uint8_t block[2 * AVB_SHA512_BLOCK_SIZE]; + uint8_t reserved[AVB_SHA512_CONTEXT_SIZE]; uint8_t buf[AVB_SHA512_DIGEST_SIZE]; /* Used for storing the final digest. */ } AvbSHA512Ctx; diff --git a/aosp/libavb1.2/src/avb/headers/avb_slot_verify.h b/aosp/libavb1.2/src/avb/headers/avb_slot_verify.h index a2c98f4..c7f3f45 100644 --- a/aosp/libavb1.2/src/avb/headers/avb_slot_verify.h +++ b/aosp/libavb1.2/src/avb/headers/avb_slot_verify.h @@ -88,7 +88,8 @@ typedef enum { AVB_HASHTREE_ERROR_MODE_RESTART, AVB_HASHTREE_ERROR_MODE_EIO, AVB_HASHTREE_ERROR_MODE_LOGGING, - AVB_HASHTREE_ERROR_MODE_MANAGED_RESTART_AND_EIO + AVB_HASHTREE_ERROR_MODE_MANAGED_RESTART_AND_EIO, + AVB_HASHTREE_ERROR_MODE_PANIC } AvbHashtreeErrorMode; /* Flags that influence how avb_slot_verify() works. @@ -157,6 +158,7 @@ typedef struct { uint8_t* data; size_t data_size; bool preloaded; + AvbSlotVerifyResult verify_result; } AvbPartitionData; /* AvbVBMetaData contains a vbmeta struct loaded from a partition when @@ -310,7 +312,7 @@ typedef struct { * in |out_digest| which must be large enough to hold a digest * of the requested type. */ -void avb_slot_verify_data_calculate_vbmeta_digest(AvbSlotVerifyData* data, +void avb_slot_verify_data_calculate_vbmeta_digest(const AvbSlotVerifyData* data, AvbDigestType digest_type, uint8_t* out_digest); diff --git a/aosp/libxbc/libxbc.c b/aosp/libxbc/libxbc.c index 6e47dee..d80ac11 100644 --- a/aosp/libxbc/libxbc.c +++ b/aosp/libxbc/libxbc.c @@ -53,7 +53,7 @@ static bool isTrailerPresent(uint64_t bootconfig_end_addr) { /* * Add a string of boot config parameters to memory appended by the trailer. */ -int32_t addBootConfigParameters(char* params, uint32_t params_size, +int32_t addBootConfigParameters(const char* params, uint32_t params_size, uint64_t bootconfig_start_addr, uint32_t bootconfig_size) { if (!params || !bootconfig_start_addr) { return -1; diff --git a/aosp/libxbc/libxbc.h b/aosp/libxbc/libxbc.h index e60cd95..bd10adf 100644 --- a/aosp/libxbc/libxbc.h +++ b/aosp/libxbc/libxbc.h @@ -43,7 +43,7 @@ extern "C" { * @param bootconfig_size size of the current bootconfig section in bytes. * @return number of bytes added to the boot config section. -1 for error. */ -int addBootConfigParameters(char *params, uint32_t params_size, +int addBootConfigParameters(const char *params, uint32_t params_size, uint64_t bootconfig_start_addr, uint32_t bootconfig_size); diff --git a/aosp/system/libufdt/utils/src/mkdtboimg.py b/aosp/system/libufdt/utils/src/mkdtboimg.py index bc33e1f..2634c76 100755 --- a/aosp/system/libufdt/utils/src/mkdtboimg.py +++ b/aosp/system/libufdt/utils/src/mkdtboimg.py @@ -1,4 +1,4 @@ -#! /usr/bin/env python +#! /usr/bin/env python3 # Copyright 2017, The Android Open Source Project # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -1018,7 +1018,7 @@ def print_usage(cmd, _): def main(): """Main entry point for mkdtboimg.""" - parser = argparse.ArgumentParser(prog='mkdtboimg.py') + parser = argparse.ArgumentParser() subparser = parser.add_subparsers(title='subcommand', description='Valid subcommands') diff --git a/aosp/system/tools/mkbootimg/gki/Android.bp b/aosp/system/tools/mkbootimg/gki/Android.bp index c62e7d8..41a1c3e 100644 --- a/aosp/system/tools/mkbootimg/gki/Android.bp +++ b/aosp/system/tools/mkbootimg/gki/Android.bp @@ -45,59 +45,3 @@ python_binary_host { "avbtool", ], } - -sh_binary_host { - name: "retrofit_gki", - src: "retrofit_gki.sh", - required: [ - "avbtool", - "mkbootimg", - "unpack_bootimg", - ], -} - -sh_test_host { - name: "retrofit_gki_test", - src: "retrofit_gki_test.sh", - data: [ - "retrofit_gki.sh", - ], - data_bins: [ - "avbtool", - "mkbootimg", - "unpack_bootimg", - ], - test_suites: [ - "general-tests", - ], -} - -genrule { - name: "gki_retrofitting_tools", - tools: [ - "soong_zip", - "retrofit_gki", - "avbtool", - "mkbootimg", - "unpack_bootimg", - ], - srcs: [ - "README.md", - ], - cmd: "STAGE_DIR=$(genDir)/gki_retrofitting_tools && " + - "rm -rf $${STAGE_DIR} && mkdir -p $${STAGE_DIR} && " + - "cp $(location retrofit_gki) $${STAGE_DIR} && " + - "cp $(location avbtool) $${STAGE_DIR} && " + - "cp $(location mkbootimg) $${STAGE_DIR} && " + - "cp $(location unpack_bootimg) $${STAGE_DIR} && " + - "cp $(in) $${STAGE_DIR} && " + - "$(location soong_zip) -o $(out) -C $(genDir) -D $${STAGE_DIR}", - out: [ - "gki_retrofitting_tools.zip", - ], - dist: { - targets: [ - "gki_retrofitting_tools", - ], - }, -} diff --git a/aosp/system/tools/mkbootimg/gki/Android.mk b/aosp/system/tools/mkbootimg/gki/Android.mk deleted file mode 100644 index c0af5ef..0000000 --- a/aosp/system/tools/mkbootimg/gki/Android.mk +++ /dev/null @@ -1,36 +0,0 @@ -# -# Copyright (C) 2022 The Android Open Source Project -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -_gsi_gki_product_names := \ - aosp_arm \ - aosp_arm64 \ - aosp_x86 \ - aosp_x86_64 \ - gsi_arm \ - gsi_arm64 \ - gsi_x86 \ - gsi_x86_64 \ - gki_arm64 \ - gki_x86_64 \ - -# Add gki_retrofitting_tools to `m dist` of GSI/GKI for easy pickup. -ifneq (,$(filter $(_gsi_gki_product_names),$(TARGET_PRODUCT))) - -droidcore-unbundled: gki_retrofitting_tools - -endif - -_gsi_gki_product_names := diff --git a/aosp/system/tools/mkbootimg/gki/README.md b/aosp/system/tools/mkbootimg/gki/README.md deleted file mode 100644 index 628e52a..0000000 --- a/aosp/system/tools/mkbootimg/gki/README.md +++ /dev/null @@ -1,74 +0,0 @@ -# GKI boot image retrofitting tools for upgrading devices - -Starting from Android T the GKI boot images consist of the generic `boot.img` -and `init_boot.img`. The `boot.img` contains the generic kernel, and -`init_boot.img` contains the generic ramdisk. -For upgrading devices whose `vendor_boot` partition is non-existent, this tool -(or spec) can be used to retrofit a set of Android T GKI `boot`, `init_boot` and -OEM `vendor_boot` partition images back into a single boot image containing the -GKI kernel plus generic and vendor ramdisks. - -## Retrofitting the boot images - -1. Download the certified GKI `boot.img`. -2. Go to the build artifacts page of `aosp_arm64` on `aosp-master` branch on - https://ci.android.com/ and download `gki_retrofitting_tools.zip`. -3. Unzip and make sure the tool is in `${PATH}`. - - ```bash - unzip gki_retrofitting_tools.zip - export PATH="$(pwd)/gki_retrofitting_tools:${PATH}" - # See tool usage: - retrofit_gki --help - ``` - -4. Create the retrofitted image. The `--version` argument lets you choose the - boot image header version of the retrofitted boot image. Only version 2 is - supported at the moment. - - ```bash - retrofit_gki --boot boot.img --init_boot init_boot.img \ - --vendor_boot vendor_boot.img --version 2 -o boot.retrofitted.img - ``` - -## Spec of the retrofitted images - -* The SOURCE `boot.img` must be officially certified Android T (or later) GKI. -* The DEST retrofitted boot image must not set the security patch level in its - header. This is because the SOURCE images might have different SPL value, thus - making the boot header SPL of the retrofitted image ill-defined. The SPL value - must be defined by the chained vbmeta image of the `boot` partition. -* The `boot signature` of the DEST image is the `boot signature` of the DEST - `boot.img`. -* The DEST retrofitted boot image must pass the `vts_gki_compliance_test` - testcase. - -### Retrofit to boot image V2 - -* The `kernel` of the DEST image must be from the SOURCE `boot.img`. -* The `ramdisk` of the DEST image must be from the SOURCE `vendor_boot.img` and - `init_boot.img`. The DEST `ramdisk` is the ramdisk concatenation of the vendor - ramdisk and generic ramdisk. -* The `recovery dtbo / acpio` must be empty. -* The `dtb` of the DEST image must be from the SOURCE `vendor_boot.img`. -* The `boot_signature` section must be appended to the end of the boot image, - and its size is zero-padded to 16KiB. - -``` - +---------------------+ - | boot header | 1 page - +---------------------+ - | kernel | n pages - +---------------------+ - | * vendor ramdisk | - | +generic ramdisk | m pages - +---------------------+ - | second stage | o pages - +---------------------+ - | recovery dtbo/acpio | 0 byte - +---------------------+ - | dtb | q pages - +---------------------+ - | * boot signature | 16384 (16K) bytes - +---------------------+ -``` diff --git a/aosp/system/tools/mkbootimg/gki/certify_bootimg.py b/aosp/system/tools/mkbootimg/gki/certify_bootimg.py index 39dcaeb..68a042e 100755 --- a/aosp/system/tools/mkbootimg/gki/certify_bootimg.py +++ b/aosp/system/tools/mkbootimg/gki/certify_bootimg.py @@ -132,7 +132,7 @@ def get_avb_image_size(image): return 0 -def add_avb_footer(image, partition_size): +def add_avb_footer(image, partition_size, extra_footer_args): """Appends a AVB hash footer to the image.""" avbtool_cmd = ['avbtool', 'add_hash_footer', '--image', image, @@ -143,6 +143,7 @@ def add_avb_footer(image, partition_size): else: avbtool_cmd.extend(['--dynamic_partition_size']) + avbtool_cmd.extend(extra_footer_args) subprocess.check_call(avbtool_cmd) @@ -160,12 +161,24 @@ def load_dict_from_file(path): return d -def load_gki_info_file(gki_info_file, extra_args): - """Loads extra args from |gki_info_file| into |extra_args|.""" +def load_gki_info_file(gki_info_file, extra_args, extra_footer_args): + """Loads extra arguments from the gki info file. + + Args: + gki_info_file: path to a gki-info.txt. + extra_args: the extra arguments forwarded to avbtool when creating + the gki certificate. + extra_footer_args: the extra arguments forwarded to avbtool when + creating the avb footer. + + """ info_dict = load_dict_from_file(gki_info_file) if 'certify_bootimg_extra_args' in info_dict: extra_args.extend( shlex.split(info_dict['certify_bootimg_extra_args'])) + if 'certify_bootimg_extra_footer_args' in info_dict: + extra_footer_args.extend( + shlex.split(info_dict['certify_bootimg_extra_footer_args'])) def get_archive_name_and_format_for_shutil(path): @@ -206,6 +219,8 @@ def parse_cmdline(): # Optional args. parser.add_argument('--extra_args', default=[], action='append', help='extra arguments to be forwarded to avbtool') + parser.add_argument('--extra_footer_args', default=[], action='append', + help='extra arguments for adding the avb footer') args = parser.parse_args() @@ -218,13 +233,21 @@ def parse_cmdline(): extra_args.extend(shlex.split(a)) args.extra_args = extra_args + extra_footer_args = [] + for a in args.extra_footer_args: + extra_footer_args.extend(shlex.split(a)) + args.extra_footer_args = extra_footer_args + if args.gki_info: - load_gki_info_file(args.gki_info, args.extra_args) + load_gki_info_file(args.gki_info, + args.extra_args, + args.extra_footer_args) return args -def certify_bootimg(boot_img, output_img, algorithm, key, extra_args): +def certify_bootimg(boot_img, output_img, algorithm, key, extra_args, + extra_footer_args): """Certify a GKI boot image by generating and appending a boot_signature.""" with tempfile.TemporaryDirectory() as temp_dir: boot_tmp = os.path.join(temp_dir, 'boot.tmp') @@ -234,26 +257,27 @@ def certify_bootimg(boot_img, output_img, algorithm, key, extra_args): add_certificate(boot_tmp, algorithm, key, extra_args) avb_partition_size = get_avb_image_size(boot_img) - add_avb_footer(boot_tmp, avb_partition_size) + add_avb_footer(boot_tmp, avb_partition_size, extra_footer_args) # We're done, copy the temp image to the final output. shutil.copy2(boot_tmp, output_img) def certify_bootimg_archive(boot_img_archive, output_archive, - algorithm, key, extra_args): + algorithm, key, extra_args, extra_footer_args): """Similar to certify_bootimg(), but for an archive of boot images.""" with tempfile.TemporaryDirectory() as unpack_dir: shutil.unpack_archive(boot_img_archive, unpack_dir) gki_info_file = os.path.join(unpack_dir, 'gki-info.txt') if os.path.exists(gki_info_file): - load_gki_info_file(gki_info_file, extra_args) + load_gki_info_file(gki_info_file, extra_args, extra_footer_args) for boot_img in glob.glob(os.path.join(unpack_dir, 'boot*.img')): print(f'Certifying {os.path.basename(boot_img)} ...') certify_bootimg(boot_img=boot_img, output_img=boot_img, - algorithm=algorithm, key=key, extra_args=extra_args) + algorithm=algorithm, key=key, extra_args=extra_args, + extra_footer_args=extra_footer_args) print(f'Making certified archive: {output_archive}') archive_file_name, archive_format = ( @@ -275,10 +299,11 @@ def main(): if args.boot_img_archive: certify_bootimg_archive(args.boot_img_archive, args.output, - args.algorithm, args.key, args.extra_args) + args.algorithm, args.key, args.extra_args, + args.extra_footer_args) else: certify_bootimg(args.boot_img, args.output, args.algorithm, - args.key, args.extra_args) + args.key, args.extra_args, args.extra_footer_args) if __name__ == '__main__': diff --git a/aosp/system/tools/mkbootimg/gki/certify_bootimg_test.py b/aosp/system/tools/mkbootimg/gki/certify_bootimg_test.py index fd7473b..ec5f505 100644 --- a/aosp/system/tools/mkbootimg/gki/certify_bootimg_test.py +++ b/aosp/system/tools/mkbootimg/gki/certify_bootimg_test.py @@ -219,6 +219,197 @@ class CertifyBootimgTest(unittest.TestCase): # C0103: invalid-name for maxDiff. self.maxDiff = None # pylint: disable=C0103 + # For AVB footers, we don't sign it so the Authentication block + # is zero bytes and the Algorithm is NONE. The footer will be + # replaced by device-specific settings when being incorporated into + # a device codebase. The footer here is just to pass some GKI + # pre-release test. + self._EXPECTED_AVB_FOOTER_BOOT_CERTIFIED = ( # pylint: disable=C0103 + 'Footer version: 1.0\n' + 'Image size: 131072 bytes\n' + 'Original image size: 24576 bytes\n' + 'VBMeta offset: 24576\n' + 'VBMeta size: 576 bytes\n' + '--\n' + 'Minimum libavb version: 1.0\n' + 'Header Block: 256 bytes\n' + 'Authentication Block: 0 bytes\n' + 'Auxiliary Block: 320 bytes\n' + 'Algorithm: NONE\n' + 'Rollback Index: 0\n' + 'Flags: 0\n' + 'Rollback Index Location: 0\n' + "Release String: 'avbtool 1.2.0'\n" + 'Descriptors:\n' + ' Hash descriptor:\n' + ' Image Size: 24576 bytes\n' + ' Hash Algorithm: sha256\n' + ' Partition Name: boot\n' + ' Salt: a11ba11b\n' + ' Digest: ' + 'c9b4ad78fae6f72f7eff939dee6078ed' + '8a75132e53f6c11ba1ec0f4b57f9eab0\n' + ' Flags: 0\n' + " Prop: avb -> 'nice'\n" + " Prop: avb_space -> 'nice to meet you'\n" + ) + + self._EXPECTED_AVB_FOOTER_BOOT_CERTIFIED_2 = ( # pylint: disable=C0103 + 'Footer version: 1.0\n' + 'Image size: 131072 bytes\n' + 'Original image size: 24576 bytes\n' + 'VBMeta offset: 24576\n' + 'VBMeta size: 576 bytes\n' + '--\n' + 'Minimum libavb version: 1.0\n' + 'Header Block: 256 bytes\n' + 'Authentication Block: 0 bytes\n' + 'Auxiliary Block: 320 bytes\n' + 'Algorithm: NONE\n' + 'Rollback Index: 0\n' + 'Flags: 0\n' + 'Rollback Index Location: 0\n' + "Release String: 'avbtool 1.2.0'\n" + 'Descriptors:\n' + ' Hash descriptor:\n' + ' Image Size: 24576 bytes\n' + ' Hash Algorithm: sha256\n' + ' Partition Name: boot\n' + ' Salt: a11ba11b\n' + ' Digest: ' + 'ae2538e78b2a30b1112cede30d858a5f' + '6f8dc2a1b109dd4a7bb28124b77d2ab0\n' + ' Flags: 0\n' + " Prop: avb -> 'nice'\n" + " Prop: avb_space -> 'nice to meet you'\n" + ) + + self._EXPECTED_AVB_FOOTER_WITH_GKI_INFO = ( # pylint: disable=C0103 + 'Footer version: 1.0\n' + 'Image size: 131072 bytes\n' + 'Original image size: 24576 bytes\n' + 'VBMeta offset: 24576\n' + 'VBMeta size: 704 bytes\n' + '--\n' + 'Minimum libavb version: 1.0\n' + 'Header Block: 256 bytes\n' + 'Authentication Block: 0 bytes\n' + 'Auxiliary Block: 448 bytes\n' + 'Algorithm: NONE\n' + 'Rollback Index: 0\n' + 'Flags: 0\n' + 'Rollback Index Location: 0\n' + "Release String: 'avbtool 1.2.0'\n" + 'Descriptors:\n' + ' Hash descriptor:\n' + ' Image Size: 24576 bytes\n' + ' Hash Algorithm: sha256\n' + ' Partition Name: boot\n' + ' Salt: a11ba11b\n' + ' Digest: ' + '363d4f246a4a5e1bba8ba8b86f5eb0cf' + '9817e4e51663ba26edccf71c3861090a\n' + ' Flags: 0\n' + " Prop: avb -> 'nice'\n" + " Prop: avb_space -> 'nice to meet you'\n" + " Prop: com.android.build.boot.os_version -> '13'\n" + " Prop: com.android.build.boot.security_patch -> '2022-05-05'\n" + ) + + self._EXPECTED_AVB_FOOTER_BOOT = ( # pylint: disable=C0103 + 'Footer version: 1.0\n' + 'Image size: 131072 bytes\n' + 'Original image size: 28672 bytes\n' + 'VBMeta offset: 28672\n' + 'VBMeta size: 704 bytes\n' + '--\n' + 'Minimum libavb version: 1.0\n' + 'Header Block: 256 bytes\n' + 'Authentication Block: 0 bytes\n' + 'Auxiliary Block: 448 bytes\n' + 'Algorithm: NONE\n' + 'Rollback Index: 0\n' + 'Flags: 0\n' + 'Rollback Index Location: 0\n' + "Release String: 'avbtool 1.2.0'\n" + 'Descriptors:\n' + ' Hash descriptor:\n' + ' Image Size: 28672 bytes\n' + ' Hash Algorithm: sha256\n' + ' Partition Name: boot\n' + ' Salt: a11ba11b\n' + ' Digest: ' + 'b93084707ba2367120e19547f17f1073' + '4c7ad8e56008ec2159d5f01b950335ad\n' + ' Flags: 0\n' + " Prop: avb -> 'nice'\n" + " Prop: avb_space -> 'nice to meet you'\n" + " Prop: com.android.build.boot.os_version -> '13'\n" + " Prop: com.android.build.boot.security_patch -> '2022-05-05'\n" + ) + + self._EXPECTED_AVB_FOOTER_BOOT_LZ4 = ( # pylint: disable=C0103 + 'Footer version: 1.0\n' + 'Image size: 262144 bytes\n' + 'Original image size: 36864 bytes\n' + 'VBMeta offset: 36864\n' + 'VBMeta size: 704 bytes\n' + '--\n' + 'Minimum libavb version: 1.0\n' + 'Header Block: 256 bytes\n' + 'Authentication Block: 0 bytes\n' + 'Auxiliary Block: 448 bytes\n' + 'Algorithm: NONE\n' + 'Rollback Index: 0\n' + 'Flags: 0\n' + 'Rollback Index Location: 0\n' + "Release String: 'avbtool 1.2.0'\n" + 'Descriptors:\n' + ' Hash descriptor:\n' + ' Image Size: 36864 bytes\n' + ' Hash Algorithm: sha256\n' + ' Partition Name: boot\n' + ' Salt: a11ba11b\n' + ' Digest: ' + '6b3f583f1bc5fbc284102e0185d02c6b' + '294f675c95b9337e89ea1e6b743af2ab\n' + ' Flags: 0\n' + " Prop: avb -> 'nice'\n" + " Prop: avb_space -> 'nice to meet you'\n" + " Prop: com.android.build.boot.os_version -> '13'\n" + " Prop: com.android.build.boot.security_patch -> '2022-05-05'\n" + ) + + self._EXPECTED_AVB_FOOTER_BOOT_GZ = ( # pylint: disable=C0103 + 'Footer version: 1.0\n' + 'Image size: 131072 bytes\n' + 'Original image size: 28672 bytes\n' + 'VBMeta offset: 28672\n' + 'VBMeta size: 576 bytes\n' + '--\n' + 'Minimum libavb version: 1.0\n' + 'Header Block: 256 bytes\n' + 'Authentication Block: 0 bytes\n' + 'Auxiliary Block: 320 bytes\n' + 'Algorithm: NONE\n' + 'Rollback Index: 0\n' + 'Flags: 0\n' + 'Rollback Index Location: 0\n' + "Release String: 'avbtool 1.2.0'\n" + 'Descriptors:\n' + ' Hash descriptor:\n' + ' Image Size: 28672 bytes\n' + ' Hash Algorithm: sha256\n' + ' Partition Name: boot\n' + ' Salt: a11ba11b\n' + ' Digest: ' + 'd2098d507e039afc6b4d7ec3de129a8d' + 'd0e0cf889c9181ebee65ce2fb25de3f5\n' + ' Flags: 0\n' + " Prop: avb -> 'nice'\n" + " Prop: avb_space -> 'nice to meet you'\n" + ) + self._EXPECTED_BOOT_SIGNATURE_RSA2048 = ( # pylint: disable=C0103 'Minimum libavb version: 1.0\n' 'Header Block: 256 bytes\n' @@ -647,6 +838,8 @@ class CertifyBootimgTest(unittest.TestCase): '--key', './testdata/testkey_rsa2048.pem', '--extra_args', '--prop gki:nice ' '--prop space:"nice to meet you"', + '--extra_footer_args', '--salt a11ba11b --prop avb:nice ' + '--prop avb_space:"nice to meet you"', '--output', boot_certified_img, ] subprocess.run(certify_bootimg_cmds, check=True, cwd=self._exec_dir) @@ -655,7 +848,13 @@ class CertifyBootimgTest(unittest.TestCase): self.assertTrue(has_avb_footer(boot_certified_img)) self.assertEqual(os.path.getsize(boot_img), os.path.getsize(boot_certified_img)) + # Checks the content in the AVB footer. + self._test_boot_signatures( + temp_out_dir, + {'boot-certified.img': + self._EXPECTED_AVB_FOOTER_BOOT_CERTIFIED}) + # Checks the content in the GKI certificate. extract_boot_signatures(boot_certified_img, temp_out_dir) self._test_boot_signatures( temp_out_dir, @@ -672,6 +871,8 @@ class CertifyBootimgTest(unittest.TestCase): '--key', './testdata/testkey_rsa4096.pem', '--extra_args', '--prop gki:nice ' '--prop space:"nice to meet you"', + '--extra_footer_args', '--salt a11ba11b --prop avb:nice ' + '--prop avb_space:"nice to meet you"', '--output', boot_certified2_img, ] subprocess.run(certify_bootimg_cmds, check=True, cwd=self._exec_dir) @@ -680,7 +881,13 @@ class CertifyBootimgTest(unittest.TestCase): self.assertTrue(has_avb_footer(boot_certified2_img)) self.assertEqual(os.path.getsize(boot_certified_img), os.path.getsize(boot_certified2_img)) + # Checks the content in the AVB footer. + self._test_boot_signatures( + temp_out_dir, + {'boot-certified2.img': + self._EXPECTED_AVB_FOOTER_BOOT_CERTIFIED_2}) + # Checks the content in the GKI certificate. extract_boot_signatures(boot_certified2_img, temp_out_dir) self._test_boot_signatures( temp_out_dir, @@ -700,7 +907,11 @@ class CertifyBootimgTest(unittest.TestCase): '-android13-0-00544-ged21d463f856 ' '--prop BRANCH:android13-5.10-2022-05 ' '--prop BUILD_NUMBER:ab8295296 ' - '--prop GKI_INFO:"added here"\n') + '--prop GKI_INFO:"added here"\n' + 'certify_bootimg_extra_footer_args=' + '--prop com.android.build.boot.os_version:13 ' + '--prop com.android.build.boot.security_patch:' + '2022-05-05\n') gki_info_path = os.path.join(temp_out_dir, 'gki-info.txt') with open(gki_info_path, 'w', encoding='utf-8') as f: f.write(gki_info) @@ -715,6 +926,8 @@ class CertifyBootimgTest(unittest.TestCase): '--key', './testdata/testkey_rsa4096.pem', '--extra_args', '--prop gki:nice ' '--prop space:"nice to meet you"', + '--extra_footer_args', '--salt a11ba11b --prop avb:nice ' + '--prop avb_space:"nice to meet you"', '--gki_info', gki_info_path, '--output', boot_certified_img, ] @@ -725,6 +938,12 @@ class CertifyBootimgTest(unittest.TestCase): self.assertEqual(os.path.getsize(boot_img), os.path.getsize(boot_certified_img)) + # Checks the content in the AVB footer. + self._test_boot_signatures( + temp_out_dir, + {'boot-certified.img': self._EXPECTED_AVB_FOOTER_WITH_GKI_INFO}) + + # Checks the content in the GKI certificate. extract_boot_signatures(boot_certified_img, temp_out_dir) self._test_boot_signatures( temp_out_dir, @@ -771,7 +990,11 @@ class CertifyBootimgTest(unittest.TestCase): '-android13-0-00544-ged21d463f856 ' '--prop BRANCH:android13-5.10-2022-05 ' '--prop BUILD_NUMBER:ab8295296 ' - '--prop SPACE:"nice to meet you"\n') + '--prop SPACE:"nice to meet you"\n' + 'certify_bootimg_extra_footer_args=' + '--prop com.android.build.boot.os_version:13 ' + '--prop com.android.build.boot.security_patch:' + '2022-05-05\n') boot_img_archive_path = generate_test_boot_image_archive( boot_img_archive_name, 'gztar', @@ -790,6 +1013,8 @@ class CertifyBootimgTest(unittest.TestCase): '--key', './testdata/testkey_rsa4096.pem', '--extra_args', '--prop gki:nice ' '--prop space:"nice to meet you"', + '--extra_footer_args', '--salt a11ba11b --prop avb:nice ' + '--prop avb_space:"nice to meet you"', '--output', boot_certified_img_archive, ] subprocess.run(certify_bootimg_cmds, check=True, cwd=self._exec_dir) @@ -806,6 +1031,13 @@ class CertifyBootimgTest(unittest.TestCase): self.assertTrue(has_avb_footer(boot_lz4_img)) self.assertEqual(os.path.getsize(boot_lz4_img), 256 * 1024) + # Checks the content in the AVB footer. + self._test_boot_signatures( + temp_out_dir, + {'boot.img': self._EXPECTED_AVB_FOOTER_BOOT, + 'boot-lz4.img': self._EXPECTED_AVB_FOOTER_BOOT_LZ4}) + + # Checks the content in the GKI certificate. self._test_boot_signatures( temp_out_dir, {'boot/boot_signature1': @@ -840,6 +1072,8 @@ class CertifyBootimgTest(unittest.TestCase): '--key', './testdata/testkey_rsa4096.pem', '--extra_args', '--prop gki:nice ' '--prop space:"nice to meet you"', + '--extra_footer_args', '--salt a11ba11b --prop avb:nice ' + '--prop avb_space:"nice to meet you"', '--output', boot_certified_img_archive, ] subprocess.run(certify_bootimg_cmds, check=True, cwd=self._exec_dir) @@ -863,6 +1097,8 @@ class CertifyBootimgTest(unittest.TestCase): '--key', './testdata/testkey_rsa4096.pem', '--extra_args', '--prop gki:nice ' '--prop space:"nice to meet you"', + '--extra_footer_args', '--salt a11ba11b --prop avb:nice ' + '--prop avb_space:"nice to meet you"', '--output', boot_certified_img_archive2, ] subprocess.run(certify_bootimg_cmds, check=True, cwd=self._exec_dir) @@ -875,6 +1111,12 @@ class CertifyBootimgTest(unittest.TestCase): self.assertTrue(has_avb_footer(boot_3_img)) self.assertEqual(os.path.getsize(boot_3_img), 128 * 1024) + # Checks the content in the AVB footer. + self._test_boot_signatures( + temp_out_dir, + {'boot-gz.img': self._EXPECTED_AVB_FOOTER_BOOT_GZ}) + + # Checks the content in the GKI certificate. self._test_boot_signatures( temp_out_dir, {'boot-gz/boot_signature1': diff --git a/aosp/system/tools/mkbootimg/gki/generate_gki_certificate.py b/aosp/system/tools/mkbootimg/gki/generate_gki_certificate.py index 17a40bc..2797cca 100755 --- a/aosp/system/tools/mkbootimg/gki/generate_gki_certificate.py +++ b/aosp/system/tools/mkbootimg/gki/generate_gki_certificate.py @@ -44,7 +44,6 @@ def generate_gki_certificate(image, avbtool, name, algorithm, key, salt, avbtool_cmd += ['--salt', salt] avbtool_cmd += additional_avb_args - print(avbtool_cmd) subprocess.check_call(avbtool_cmd) diff --git a/aosp/system/tools/mkbootimg/gki/retrofit_gki.sh b/aosp/system/tools/mkbootimg/gki/retrofit_gki.sh deleted file mode 100755 index 01af7fa..0000000 --- a/aosp/system/tools/mkbootimg/gki/retrofit_gki.sh +++ /dev/null @@ -1,231 +0,0 @@ -#!/bin/bash -# -# Copyright (C) 2022 The Android Open Source Project -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -# -# Retrofits GKI boot images for upgrading devices. -# - -set -eo errtrace - -usage() { - cat <&2 "ERROR:" "${@}" - exit 1 -} - -file_size() { - stat -c '%s' "$1" -} - -get_arg() { - local arg="$1" - shift - while [[ "$#" -gt 0 ]]; do - if [[ "$1" == "${arg}" ]]; then - shift - echo "$1" - return - fi - shift - done -} - -TEMP_DIR="$(mktemp -d --tmpdir retrofit_gki.XXXXXXXX)" -readonly TEMP_DIR - -exit_handler() { - readonly EXIT_CODE="$?" - rm -rf "${TEMP_DIR}" ||: - exit "${EXIT_CODE}" -} - -trap exit_handler EXIT -trap 'die "line ${LINENO}, ${FUNCNAME:-
}(): \"${BASH_COMMAND}\" returned \"$?\"" ' ERR - -while [[ "$1" =~ ^- ]]; do - case "$1" in - --boot ) - shift - BOOT_IMAGE="$1" - ;; - --init_boot ) - shift - INIT_BOOT_IMAGE="$1" - ;; - --vendor_boot ) - shift - VENDOR_BOOT_IMAGE="$1" - ;; - --version ) - shift - OUTPUT_BOOT_IMAGE_VERSION="$1" - ;; - -o | --output ) - shift - OUTPUT_BOOT_IMAGE="$1" - ;; - -v | --verbose ) - VERBOSE=true - ;; - -- ) - shift - break - ;; - -h | --help | --usage ) - usage - exit 0 - ;; - * ) - echo >&2 "Unexpected flag: '$1'" - usage >&2 - exit 1 - ;; - esac - shift -done - -declare -ir OUTPUT_BOOT_IMAGE_VERSION -readonly BOOT_IMAGE -readonly INIT_BOOT_IMAGE -readonly VENDOR_BOOT_IMAGE -readonly OUTPUT_BOOT_IMAGE -readonly VERBOSE - -# Make sure the input arguments make sense. -[[ -f "${BOOT_IMAGE}" ]] || - die "argument '--boot': not a regular file: '${BOOT_IMAGE}'" -[[ -f "${INIT_BOOT_IMAGE}" ]] || - die "argument '--init_boot': not a regular file: '${INIT_BOOT_IMAGE}'" -if [[ "${OUTPUT_BOOT_IMAGE_VERSION}" -lt 2 ]] || [[ "${OUTPUT_BOOT_IMAGE_VERSION}" -gt 4 ]]; then - die "argument '--version': valid choices are {2, 3, 4}" -elif [[ "${OUTPUT_BOOT_IMAGE_VERSION}" -eq 2 ]]; then - [[ -f "${VENDOR_BOOT_IMAGE}" ]] || - die "argument '--vendor_boot': not a regular file: '${VENDOR_BOOT_IMAGE}'" -fi -[[ -z "${OUTPUT_BOOT_IMAGE}" ]] && - die "argument '--output': cannot be empty" - -readonly BOOT_IMAGE_WITHOUT_AVB_FOOTER="${TEMP_DIR}/boot.img.without_avb_footer" -readonly BOOT_DIR="${TEMP_DIR}/boot" -readonly INIT_BOOT_DIR="${TEMP_DIR}/init_boot" -readonly VENDOR_BOOT_DIR="${TEMP_DIR}/vendor_boot" -readonly VENDOR_BOOT_MKBOOTIMG_ARGS="${TEMP_DIR}/vendor_boot.mkbootimg_args" -readonly OUTPUT_RAMDISK="${TEMP_DIR}/out.ramdisk" -readonly OUTPUT_BOOT_SIGNATURE="${TEMP_DIR}/out.boot_signature" - -readonly AVBTOOL="${AVBTOOL:-avbtool}" -readonly MKBOOTIMG="${MKBOOTIMG:-mkbootimg}" -readonly UNPACK_BOOTIMG="${UNPACK_BOOTIMG:-unpack_bootimg}" - -# Fixed boot signature size for easy discovery in VTS. -readonly BOOT_SIGNATURE_SIZE=$(( 16 << 10 )) - - -# -# Preparations are done. Now begin the actual work. -# - -# Copy the boot image because `avbtool erase_footer` edits the file in-place. -cp "${BOOT_IMAGE}" "${BOOT_IMAGE_WITHOUT_AVB_FOOTER}" -( [[ -n "${VERBOSE}" ]] && set -x - "${AVBTOOL}" erase_footer --image "${BOOT_IMAGE_WITHOUT_AVB_FOOTER}" 2>/dev/null ||: - tail -c "${BOOT_SIGNATURE_SIZE}" "${BOOT_IMAGE_WITHOUT_AVB_FOOTER}" > "${OUTPUT_BOOT_SIGNATURE}" - "${UNPACK_BOOTIMG}" --boot_img "${BOOT_IMAGE}" --out "${BOOT_DIR}" >/dev/null - "${UNPACK_BOOTIMG}" --boot_img "${INIT_BOOT_IMAGE}" --out "${INIT_BOOT_DIR}" >/dev/null -) -if [[ "$(file_size "${OUTPUT_BOOT_SIGNATURE}")" -ne "${BOOT_SIGNATURE_SIZE}" ]]; then - die "boot signature size must be equal to ${BOOT_SIGNATURE_SIZE}" -fi - -declare -a mkbootimg_args=() - -if [[ "${OUTPUT_BOOT_IMAGE_VERSION}" -eq 4 ]]; then - mkbootimg_args+=( \ - --header_version 4 \ - --kernel "${BOOT_DIR}/kernel" \ - --ramdisk "${INIT_BOOT_DIR}/ramdisk" \ - ) -elif [[ "${OUTPUT_BOOT_IMAGE_VERSION}" -eq 3 ]]; then - mkbootimg_args+=( \ - --header_version 3 \ - --kernel "${BOOT_DIR}/kernel" \ - --ramdisk "${INIT_BOOT_DIR}/ramdisk" \ - ) -elif [[ "${OUTPUT_BOOT_IMAGE_VERSION}" -eq 2 ]]; then - ( [[ -n "${VERBOSE}" ]] && set -x - "${UNPACK_BOOTIMG}" --boot_img "${VENDOR_BOOT_IMAGE}" --out "${VENDOR_BOOT_DIR}" \ - --format=mkbootimg -0 > "${VENDOR_BOOT_MKBOOTIMG_ARGS}" - cat "${VENDOR_BOOT_DIR}/vendor_ramdisk" "${INIT_BOOT_DIR}/ramdisk" > "${OUTPUT_RAMDISK}" - ) - - declare -a vendor_boot_args=() - while IFS= read -r -d '' ARG; do - vendor_boot_args+=("${ARG}") - done < "${VENDOR_BOOT_MKBOOTIMG_ARGS}" - - pagesize="$(get_arg --pagesize "${vendor_boot_args[@]}")" - kernel_offset="$(get_arg --kernel_offset "${vendor_boot_args[@]}")" - ramdisk_offset="$(get_arg --ramdisk_offset "${vendor_boot_args[@]}")" - tags_offset="$(get_arg --tags_offset "${vendor_boot_args[@]}")" - dtb_offset="$(get_arg --dtb_offset "${vendor_boot_args[@]}")" - kernel_cmdline="$(get_arg --vendor_cmdline "${vendor_boot_args[@]}")" - - mkbootimg_args+=( \ - --header_version 2 \ - --base 0 \ - --kernel_offset "${kernel_offset}" \ - --ramdisk_offset "${ramdisk_offset}" \ - --second_offset 0 \ - --tags_offset "${tags_offset}" \ - --dtb_offset "${dtb_offset}" \ - --cmdline "${kernel_cmdline}" \ - --pagesize "${pagesize}" \ - --kernel "${BOOT_DIR}/kernel" \ - --ramdisk "${OUTPUT_RAMDISK}" \ - ) - if [[ -f "${VENDOR_BOOT_DIR}/dtb" ]]; then - mkbootimg_args+=(--dtb "${VENDOR_BOOT_DIR}/dtb") - fi -fi - -( [[ -n "${VERBOSE}" ]] && set -x - "${MKBOOTIMG}" "${mkbootimg_args[@]}" --output "${OUTPUT_BOOT_IMAGE}" - cat "${OUTPUT_BOOT_SIGNATURE}" >> "${OUTPUT_BOOT_IMAGE}" -) diff --git a/aosp/system/tools/mkbootimg/gki/retrofit_gki_test.sh b/aosp/system/tools/mkbootimg/gki/retrofit_gki_test.sh deleted file mode 100755 index b3cb0a5..0000000 --- a/aosp/system/tools/mkbootimg/gki/retrofit_gki_test.sh +++ /dev/null @@ -1,144 +0,0 @@ -#!/bin/bash -# -# Copyright (C) 2022 The Android Open Source Project -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -set -eo errtrace - -die() { - echo >&2 "ERROR:" "${@}" - exit 1 -} - -trap 'die "line ${LINENO}, ${FUNCNAME:-
}(): \"${BASH_COMMAND}\" returned \"$?\"" ' ERR - -# Figure out where we are and where to look for test executables. -cd "$(dirname "${BASH_SOURCE[0]}")" -TEST_DIR="$(pwd)" -readonly TEST_DIR -readonly TEMP_DIR="${TEST_DIR}/stage.retrofit_gki_test" - -export PATH="${TEST_DIR}:${PATH}" -rm -rf "${TEMP_DIR}" -mkdir -p "${TEMP_DIR}" - -# Generate some test files. -readonly TEST_DTB="${TEMP_DIR}/dtb" -readonly TEST_KERNEL="${TEMP_DIR}/kernel" -readonly TEST_RAMDISK="${TEMP_DIR}/ramdisk" -readonly TEST_VENDOR_RAMDISK="${TEMP_DIR}/vendor_ramdisk" -readonly TEST_BOOT_SIGNATURE="${TEMP_DIR}/boot.boot_signature" -readonly TEST_V2_RETROFITTED_RAMDISK="${TEMP_DIR}/retrofitted.ramdisk" -readonly TEST_BOOT_IMAGE="${TEMP_DIR}/boot.img" -readonly TEST_INIT_BOOT_IMAGE="${TEMP_DIR}/init_boot.img" -readonly TEST_VENDOR_BOOT_IMAGE="${TEMP_DIR}/vendor_boot.img" - -( # Run these in subshell because dd is noisy. - dd if=/dev/urandom of="${TEST_DTB}" bs=1024 count=10 - dd if=/dev/urandom of="${TEST_KERNEL}" bs=1024 count=10 - dd if=/dev/urandom of="${TEST_RAMDISK}" bs=1024 count=10 - dd if=/dev/urandom of="${TEST_VENDOR_RAMDISK}" bs=1024 count=10 - dd if=/dev/urandom of="${TEST_BOOT_SIGNATURE}" bs=1024 count=16 -) 2> /dev/null - -cat "${TEST_VENDOR_RAMDISK}" "${TEST_RAMDISK}" > "${TEST_V2_RETROFITTED_RAMDISK}" - -mkbootimg \ - --header_version 4 \ - --kernel "${TEST_KERNEL}" \ - --output "${TEST_BOOT_IMAGE}" -cat "${TEST_BOOT_SIGNATURE}" >> "${TEST_BOOT_IMAGE}" -avbtool add_hash_footer --image "${TEST_BOOT_IMAGE}" --partition_name boot --partition_size $((20 << 20)) - -mkbootimg \ - --header_version 4 \ - --ramdisk "${TEST_RAMDISK}" \ - --output "${TEST_INIT_BOOT_IMAGE}" -mkbootimg \ - --header_version 4 \ - --pagesize 4096 \ - --dtb "${TEST_DTB}" \ - --vendor_ramdisk "${TEST_VENDOR_RAMDISK}" \ - --vendor_boot "${TEST_VENDOR_BOOT_IMAGE}" - -readonly RETROFITTED_IMAGE="${TEMP_DIR}/retrofitted_boot.img" -readonly RETROFITTED_IMAGE_DIR="${TEMP_DIR}/retrofitted_boot.img.unpack" -readonly BOOT_SIGNATURE_SIZE=$(( 16 << 10 )) - - -# -# Begin test. -# -echo >&2 "TEST: retrofit to boot v4" - -retrofit_gki.sh \ - --boot "${TEST_BOOT_IMAGE}" \ - --init_boot "${TEST_INIT_BOOT_IMAGE}" \ - --version 4 \ - --output "${RETROFITTED_IMAGE}" - -rm -rf "${RETROFITTED_IMAGE_DIR}" -unpack_bootimg --boot_img "${RETROFITTED_IMAGE}" --out "${RETROFITTED_IMAGE_DIR}" > /dev/null -tail -c "${BOOT_SIGNATURE_SIZE}" "${RETROFITTED_IMAGE}" > "${RETROFITTED_IMAGE_DIR}/boot_signature" - -cmp -s "${TEST_KERNEL}" "${RETROFITTED_IMAGE_DIR}/kernel" || - die "unexpected diff: kernel" -cmp -s "${TEST_RAMDISK}" "${RETROFITTED_IMAGE_DIR}/ramdisk" || - die "unexpected diff: ramdisk" -cmp -s "${TEST_BOOT_SIGNATURE}" "${RETROFITTED_IMAGE_DIR}/boot_signature" || - die "unexpected diff: boot signature" - - -echo >&2 "TEST: retrofit to boot v3" - -retrofit_gki.sh \ - --boot "${TEST_BOOT_IMAGE}" \ - --init_boot "${TEST_INIT_BOOT_IMAGE}" \ - --version 3 \ - --output "${RETROFITTED_IMAGE}" - -rm -rf "${RETROFITTED_IMAGE_DIR}" -unpack_bootimg --boot_img "${RETROFITTED_IMAGE}" --out "${RETROFITTED_IMAGE_DIR}" > /dev/null -tail -c "${BOOT_SIGNATURE_SIZE}" "${RETROFITTED_IMAGE}" > "${RETROFITTED_IMAGE_DIR}/boot_signature" - -cmp -s "${TEST_KERNEL}" "${RETROFITTED_IMAGE_DIR}/kernel" || - die "unexpected diff: kernel" -cmp -s "${TEST_RAMDISK}" "${RETROFITTED_IMAGE_DIR}/ramdisk" || - die "unexpected diff: ramdisk" -cmp -s "${TEST_BOOT_SIGNATURE}" "${RETROFITTED_IMAGE_DIR}/boot_signature" || - die "unexpected diff: boot signature" - - -echo >&2 "TEST: retrofit to boot v2" - -retrofit_gki.sh \ - --boot "${TEST_BOOT_IMAGE}" \ - --init_boot "${TEST_INIT_BOOT_IMAGE}" \ - --vendor_boot "${TEST_VENDOR_BOOT_IMAGE}" \ - --version 2 \ - --output "${RETROFITTED_IMAGE}" - -rm -rf "${RETROFITTED_IMAGE_DIR}" -unpack_bootimg --boot_img "${RETROFITTED_IMAGE}" --out "${RETROFITTED_IMAGE_DIR}" > /dev/null -tail -c "${BOOT_SIGNATURE_SIZE}" "${RETROFITTED_IMAGE}" > "${RETROFITTED_IMAGE_DIR}/boot_signature" - -cmp -s "${TEST_DTB}" "${RETROFITTED_IMAGE_DIR}/dtb" || - die "unexpected diff: dtb" -cmp -s "${TEST_KERNEL}" "${RETROFITTED_IMAGE_DIR}/kernel" || - die "unexpected diff: kernel" -cmp -s "${TEST_V2_RETROFITTED_RAMDISK}" "${RETROFITTED_IMAGE_DIR}/ramdisk" || - die "unexpected diff: ramdisk" -cmp -s "${TEST_BOOT_SIGNATURE}" "${RETROFITTED_IMAGE_DIR}/boot_signature" || - die "unexpected diff: boot signature" diff --git a/bbootimg/build.gradle.kts b/bbootimg/build.gradle.kts index 9a3a060..c0a59b9 100644 --- a/bbootimg/build.gradle.kts +++ b/bbootimg/build.gradle.kts @@ -15,7 +15,7 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinCompile plugins { - kotlin("jvm") version "1.7.20" + kotlin("jvm") version "1.8.0" application } @@ -60,7 +60,7 @@ tasks.withType().all { kotlinOptions { freeCompilerArgs += "-opt-in=kotlin.RequiresOptIn" freeCompilerArgs += "-opt-in=kotlin.ExperimentalUnsignedTypes" - jvmTarget = "11" + jvmTarget = "17" } } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 8049c68..070cb70 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/helper/build.gradle.kts b/helper/build.gradle.kts index 4c897e8..61d0ba5 100644 --- a/helper/build.gradle.kts +++ b/helper/build.gradle.kts @@ -15,7 +15,7 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinCompile plugins { - kotlin("jvm") version "1.7.20" + kotlin("jvm") version "1.8.0" `java-library` application } @@ -53,7 +53,7 @@ tasks.withType().all { kotlinOptions { freeCompilerArgs += "-opt-in=kotlin.RequiresOptIn" freeCompilerArgs += "-opt-in=kotlin.ExperimentalUnsignedTypes" - jvmTarget = "11" + jvmTarget = "17" } } diff --git a/integrationTest.py b/integrationTest.py index 0b95c7b..c622cb8 100755 --- a/integrationTest.py +++ b/integrationTest.py @@ -161,8 +161,9 @@ def main(): verifySingleJson("%s/issue_59/recovery.json" % resDir2, func = lambda: shutil.rmtree("build/unzip_boot/root", ignore_errors = False)) # Issue 71: dtbo if platform.system() != "Darwin": - verifySingleDir(resDir2, "issue_71") - verifySingleDir(resDir2, "issue_71/redfin") + pass + #verifySingleDir(resDir2, "issue_71") + #verifySingleDir(resDir2, "issue_71/redfin") else: log.info("dtbo not fully supported on MacOS, skip testing") # Issue 83: init_boot diff --git a/tools/work_from_China.diff b/tools/work_from_China.diff index c674b6c..7db8da6 100644 --- a/tools/work_from_China.diff +++ b/tools/work_from_China.diff @@ -44,8 +44,8 @@ index 8049c68..2e33ce8 100644 @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists --distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-bin.zip -+distributionUrl=https\://mirrors.cloud.tencent.com/gradle/gradle-7.5-bin.zip +-distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-bin.zip ++distributionUrl=https\://mirrors.cloud.tencent.com/gradle/gradle-7.6-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/helper/build.gradle.kts b/helper/build.gradle.kts