Snap for 8505378 from cade007f982c6ab6b0993feb66232d57a924035b to mainline-go-adservices-release

Change-Id: Icabecfac190f654ef00bb9f962cf39e229b71b55
diff --git a/Android.bp b/Android.bp
index 77a5a32..65b6ac2 100644
--- a/Android.bp
+++ b/Android.bp
@@ -91,6 +91,20 @@
     ],
 }
 
+python_binary_host {
+    name: "certify_bootimg",
+    defaults: ["mkbootimg_defaults"],
+    main: "gki/certify_bootimg.py",
+    srcs: [
+        "gki/certify_bootimg.py",
+        "gki/generate_gki_certificate.py",
+        "unpack_bootimg.py",
+    ],
+    required: [
+        "avbtool",
+    ],
+}
+
 python_test_host {
     name: "mkbootimg_test",
     defaults: ["mkbootimg_defaults"],
diff --git a/gki/Android.bp b/gki/Android.bp
index 5173852..c62e7d8 100644
--- a/gki/Android.bp
+++ b/gki/Android.bp
@@ -16,20 +16,6 @@
     default_applicable_licenses: ["Android-Apache-2.0"],
 }
 
-python_binary_host {
-    name: "certify_bootimg",
-    defaults: ["mkbootimg_defaults"],
-    main: "certify_bootimg.py",
-    srcs: [
-        "certify_bootimg.py",
-        "generate_gki_certificate.py",
-    ],
-    required: [
-        "avbtool",
-        "unpack_bootimg",
-    ],
-}
-
 python_test_host {
     name: "certify_bootimg_test",
     defaults: ["mkbootimg_defaults"],
diff --git a/gki/certify_bootimg.py b/gki/certify_bootimg.py
index 5a99c1f..9a7b058 100755
--- a/gki/certify_bootimg.py
+++ b/gki/certify_bootimg.py
@@ -25,7 +25,8 @@
 import subprocess
 import tempfile
 
-from generate_gki_certificate import generate_gki_certificate
+from gki.generate_gki_certificate import generate_gki_certificate
+from unpack_bootimg import unpack_bootimg
 
 BOOT_SIGNATURE_SIZE = 16 * 1024
 
@@ -33,14 +34,7 @@
 def get_kernel(boot_img):
     """Extracts the kernel from |boot_img| and returns it."""
     with tempfile.TemporaryDirectory() as unpack_dir:
-        unpack_bootimg_cmd = [
-            'unpack_bootimg',
-            '--boot_img', boot_img,
-            '--out', unpack_dir,
-        ]
-        subprocess.run(unpack_bootimg_cmd, check=True,
-                       stdout=subprocess.DEVNULL)
-
+        unpack_bootimg(boot_img, unpack_dir)
         with open(os.path.join(unpack_dir, 'kernel'), 'rb') as kernel:
             kernel_bytes = kernel.read()
             assert len(kernel_bytes) > 0
@@ -219,8 +213,12 @@
     with tempfile.TemporaryDirectory() as unzip_dir:
         shutil.unpack_archive(boot_img_zip, unzip_dir)
 
-        info_dict = load_dict_from_file(os.path.join(unzip_dir, 'gki-info.txt'))
-        extra_args.extend(shlex.split(info_dict['certify_bootimg_extra_args']))
+        gki_info_file = os.path.join(unzip_dir, 'gki-info.txt')
+        if os.path.exists(gki_info_file):
+            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']))
 
         for boot_img in glob.glob(os.path.join(unzip_dir, 'boot-*.img')):
             print(f'Certifying {os.path.basename(boot_img)} ...')
diff --git a/gki/certify_bootimg_test.py b/gki/certify_bootimg_test.py
index 5fffed2..8c7c4d3 100644
--- a/gki/certify_bootimg_test.py
+++ b/gki/certify_bootimg_test.py
@@ -68,7 +68,7 @@
         subprocess.check_call(avbtool_cmd)
 
 
-def generate_test_boot_image_archive(output_zip, boot_img_info):
+def generate_test_boot_image_archive(output_zip, boot_img_info, gki_info=None):
     """Generates a zip archive of test boot images.
 
     It also adds a file gki-info.txt, which contains additional settings for
@@ -80,6 +80,8 @@
           partition_size) tuples. e.g.,
           [('boot-1.0.img', 4096, 4 * 1024),
            ('boot-2.0.img', 8192, 8 * 1024)].
+        gki_info: the file content to be written into 'gki-info.txt' in the
+          |output_zip|.
     """
     with tempfile.TemporaryDirectory() as temp_out_dir:
         for name, kernel_size, partition_size in boot_img_info:
@@ -89,14 +91,10 @@
                                      seed=name,
                                      avb_partition_size=partition_size)
 
-        gki_info = os.path.join(temp_out_dir, 'gki-info.txt')
-        with open(gki_info, 'w', encoding='utf-8') as f:
-            f.write('certify_bootimg_extra_args='
-                    '--prop KERNEL_RELEASE:5.10.42'
-                    '-android13-0-00544-ged21d463f856 '
-                    '--prop BRANCH:android13-5.10-2022-05 '
-                    '--prop BUILD_NUMBER:ab8295296 '
-                    '--prop SPACE:"nice to meet you"\n')
+        if gki_info:
+            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)
 
         archive_base_name = os.path.splitext(output_zip)[0]
         shutil.make_archive(archive_base_name, 'zip', temp_out_dir)
@@ -441,6 +439,58 @@
             "    Prop: SPACE -> 'nice to meet you'\n"
         )
 
+        self._EXPECTED_BOOT_3_0_SIGNATURE1_RSA4096 = (   # pylint: disable=C0103
+            'Minimum libavb version:   1.0\n'
+            'Header Block:             256 bytes\n'
+            'Authentication Block:     576 bytes\n'
+            'Auxiliary Block:          1344 bytes\n'
+            'Public key (sha1):        '
+            '2597c218aae470a130f61162feaae70afd97f011\n'
+            'Algorithm:                SHA256_RSA4096\n'    # RSA4096
+            '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:            12288 bytes\n'
+            '      Hash Algorithm:        sha256\n'
+            '      Partition Name:        boot\n'           # boot
+            '      Salt:                  d00df00d\n'
+            '      Digest:                '
+            '9b9cd845a367d7fc9b61d6ac02b0e7c9'
+            'dc3d3b219abf60dd6e19359f0353c917\n'
+            '      Flags:                 0\n'
+            "    Prop: gki -> 'nice'\n"
+            "    Prop: space -> 'nice to meet you'\n"
+        )
+
+        self._EXPECTED_BOOT_3_0_SIGNATURE2_RSA4096 = (   # pylint: disable=C0103
+            'Minimum libavb version:   1.0\n'
+            'Header Block:             256 bytes\n'
+            'Authentication Block:     576 bytes\n'
+            'Auxiliary Block:          1344 bytes\n'
+            'Public key (sha1):        '
+            '2597c218aae470a130f61162feaae70afd97f011\n'
+            'Algorithm:                SHA256_RSA4096\n'    # RSA4096
+            '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:            8192 bytes\n'
+            '      Hash Algorithm:        sha256\n'
+            '      Partition Name:        generic_kernel\n' # generic_kernel
+            '      Salt:                  d00df00d\n'
+            '      Digest:                '
+            '0cd7d331ed9b32dcd92f00e2cac75595'
+            '52199170afe788a8fcf1954f9ea072d0\n'
+            '      Flags:                 0\n'
+            "    Prop: gki -> 'nice'\n"
+            "    Prop: space -> 'nice to meet you'\n"
+        )
+
     def _test_boot_signatures(self, signatures_dir, expected_signatures_info):
         """Tests the info of each boot signature under the signature directory.
 
@@ -600,11 +650,18 @@
         """Tests certify_bootimg for a boot-img.zip."""
         with tempfile.TemporaryDirectory() as temp_out_dir:
             boot_img_zip = os.path.join(temp_out_dir, 'boot-img.zip')
+            gki_info = ('certify_bootimg_extra_args='
+                        '--prop KERNEL_RELEASE:5.10.42'
+                        '-android13-0-00544-ged21d463f856 '
+                        '--prop BRANCH:android13-5.10-2022-05 '
+                        '--prop BUILD_NUMBER:ab8295296 '
+                        '--prop SPACE:"nice to meet you"\n')
             generate_test_boot_image_archive(
                 boot_img_zip,
                 # A list of (boot_img_name, kernel_size, partition_size).
                 [('boot-1.0.img', 8 * 1024, 128 * 1024),
-                 ('boot-2.0.img', 16 * 1024, 256 * 1024)])
+                 ('boot-2.0.img', 16 * 1024, 256 * 1024)],
+                gki_info)
 
             # Certify the boot image archive, with a RSA4096 key.
             boot_certified_img_zip = os.path.join(temp_out_dir,
@@ -643,6 +700,69 @@
                  'boot-2.0/boot_signature2':
                     self._EXPECTED_BOOT_2_0_SIGNATURE2_RSA4096})
 
+    def test_certify_bootimg_archive_without_gki_info(self):
+        """Tests certify_bootimg for a boot-img.zip."""
+        with tempfile.TemporaryDirectory() as temp_out_dir:
+            boot_img_zip = os.path.join(temp_out_dir, 'boot-img.zip')
+
+            # Checks ceritfy_bootimg works for a boot-img.zip without a
+            # gki-info.txt.
+            generate_test_boot_image_archive(
+                boot_img_zip,
+                # A list of (boot_img_name, kernel_size, partition_size).
+                [('boot-3.0.img', 8 * 1024, 128 * 1024)],
+                gki_info=None)
+            # Certify the boot image archive, with a RSA4096 key.
+            boot_certified_img_zip = os.path.join(temp_out_dir,
+                                                  'boot-certified-img.zip')
+            certify_bootimg_cmds = [
+                'certify_bootimg',
+                '--boot_img_zip', boot_img_zip,
+                '--algorithm', 'SHA256_RSA4096',
+                '--key', './testdata/testkey_rsa4096.pem',
+                '--extra_args', '--prop gki:nice '
+                '--prop space:"nice to meet you"',
+                '--output', boot_certified_img_zip,
+            ]
+            subprocess.run(certify_bootimg_cmds, check=True, cwd=self._exec_dir)
+
+            # Checks ceritfy_bootimg works for a boot-img.zip with a special
+            # gki-info.txt.
+            generate_test_boot_image_archive(
+                boot_img_zip,
+                # A list of (boot_img_name, kernel_size, partition_size).
+                [('boot-3.0.img', 8 * 1024, 128 * 1024)],
+                gki_info='a=b\n'
+                         'c=d\n')
+            # Certify the boot image archive, with a RSA4096 key.
+            boot_certified_img_zip = os.path.join(temp_out_dir,
+                                                  'boot-certified-img.zip')
+            certify_bootimg_cmds = [
+                'certify_bootimg',
+                '--boot_img_zip', boot_img_zip,
+                '--algorithm', 'SHA256_RSA4096',
+                '--key', './testdata/testkey_rsa4096.pem',
+                '--extra_args', '--prop gki:nice '
+                '--prop space:"nice to meet you"',
+                '--output', boot_certified_img_zip,
+            ]
+            subprocess.run(certify_bootimg_cmds, check=True, cwd=self._exec_dir)
+
+            extract_boot_archive_with_signatures(boot_certified_img_zip,
+                                                 temp_out_dir)
+
+            # Checks an AVB footer exists and the image size remains.
+            boot_3_img = os.path.join(temp_out_dir, 'boot-3.0.img')
+            self.assertTrue(has_avb_footer(boot_3_img))
+            self.assertEqual(os.path.getsize(boot_3_img), 128 * 1024)
+
+            self._test_boot_signatures(
+                temp_out_dir,
+                {'boot-3.0/boot_signature1':
+                    self._EXPECTED_BOOT_3_0_SIGNATURE1_RSA4096,
+                 'boot-3.0/boot_signature2':
+                    self._EXPECTED_BOOT_3_0_SIGNATURE2_RSA4096})
+
 
 # I don't know how, but we need both the logger configuration and verbosity
 # level > 2 to make atest work. And yes this line needs to be at the very top
diff --git a/unpack_bootimg.py b/unpack_bootimg.py
index 5c7d24c..462190f 100755
--- a/unpack_bootimg.py
+++ b/unpack_bootimg.py
@@ -19,7 +19,7 @@
 Extracts the kernel, ramdisk, second bootloader, dtb and recovery dtbo images.
 """
 
-from argparse import ArgumentParser, FileType, RawDescriptionHelpFormatter
+from argparse import ArgumentParser, RawDescriptionHelpFormatter
 from struct import unpack
 import os
 import shlex
@@ -181,12 +181,12 @@
         return args
 
 
-def unpack_boot_image(args):
+def unpack_boot_image(boot_img, output_dir):
     """extracts kernel, ramdisk, second bootloader and recovery dtbo"""
     info = BootImageInfoFormatter()
-    info.boot_magic = unpack('8s', args.boot_img.read(8))[0].decode()
+    info.boot_magic = unpack('8s', boot_img.read(8))[0].decode()
 
-    kernel_ramdisk_second_info = unpack('9I', args.boot_img.read(9 * 4))
+    kernel_ramdisk_second_info = unpack('9I', boot_img.read(9 * 4))
     # header_version is always at [8] regardless of the value of header_version.
     info.header_version = kernel_ramdisk_second_info[8]
 
@@ -199,7 +199,7 @@
         info.second_load_address = kernel_ramdisk_second_info[5]
         info.tags_load_address = kernel_ramdisk_second_info[6]
         info.page_size = kernel_ramdisk_second_info[7]
-        os_version_patch_level = unpack('I', args.boot_img.read(1 * 4))[0]
+        os_version_patch_level = unpack('I', boot_img.read(1 * 4))[0]
     else:
         info.kernel_size = kernel_ramdisk_second_info[0]
         info.ramdisk_size = kernel_ramdisk_second_info[1]
@@ -212,31 +212,31 @@
 
     if info.header_version < 3:
         info.product_name = cstr(unpack('16s',
-                                        args.boot_img.read(16))[0].decode())
-        info.cmdline = cstr(unpack('512s', args.boot_img.read(512))[0].decode())
-        args.boot_img.read(32)  # ignore SHA
+                                        boot_img.read(16))[0].decode())
+        info.cmdline = cstr(unpack('512s', boot_img.read(512))[0].decode())
+        boot_img.read(32)  # ignore SHA
         info.extra_cmdline = cstr(unpack('1024s',
-                                         args.boot_img.read(1024))[0].decode())
+                                         boot_img.read(1024))[0].decode())
     else:
         info.cmdline = cstr(unpack('1536s',
-                                   args.boot_img.read(1536))[0].decode())
+                                   boot_img.read(1536))[0].decode())
 
     if info.header_version in {1, 2}:
-        info.recovery_dtbo_size = unpack('I', args.boot_img.read(1 * 4))[0]
-        info.recovery_dtbo_offset = unpack('Q', args.boot_img.read(8))[0]
-        info.boot_header_size = unpack('I', args.boot_img.read(4))[0]
+        info.recovery_dtbo_size = unpack('I', boot_img.read(1 * 4))[0]
+        info.recovery_dtbo_offset = unpack('Q', boot_img.read(8))[0]
+        info.boot_header_size = unpack('I', boot_img.read(4))[0]
     else:
         info.recovery_dtbo_size = 0
 
     if info.header_version == 2:
-        info.dtb_size = unpack('I', args.boot_img.read(4))[0]
-        info.dtb_load_address = unpack('Q', args.boot_img.read(8))[0]
+        info.dtb_size = unpack('I', boot_img.read(4))[0]
+        info.dtb_load_address = unpack('Q', boot_img.read(8))[0]
     else:
         info.dtb_size = 0
         info.dtb_load_address = 0
 
     if info.header_version >= 4:
-        info.boot_signature_size = unpack('I', args.boot_img.read(4))[0]
+        info.boot_signature_size = unpack('I', boot_img.read(4))[0]
     else:
         info.boot_signature_size = 0
 
@@ -284,10 +284,10 @@
         image_info_list.append((boot_signature_offset, info.boot_signature_size,
                                 'boot_signature'))
 
-    create_out_dir(args.out)
+    create_out_dir(output_dir)
     for offset, size, name in image_info_list:
-        extract_image(offset, size, args.boot_img, os.path.join(args.out, name))
-    info.image_dir = args.out
+        extract_image(offset, size, boot_img, os.path.join(output_dir, name))
+    info.image_dir = output_dir
 
     return info
 
@@ -378,20 +378,20 @@
         return args
 
 
-def unpack_vendor_boot_image(args):
+def unpack_vendor_boot_image(boot_img, output_dir):
     info = VendorBootImageInfoFormatter()
-    info.boot_magic = unpack('8s', args.boot_img.read(8))[0].decode()
-    info.header_version = unpack('I', args.boot_img.read(4))[0]
-    info.page_size = unpack('I', args.boot_img.read(4))[0]
-    info.kernel_load_address = unpack('I', args.boot_img.read(4))[0]
-    info.ramdisk_load_address = unpack('I', args.boot_img.read(4))[0]
-    info.vendor_ramdisk_size = unpack('I', args.boot_img.read(4))[0]
-    info.cmdline = cstr(unpack('2048s', args.boot_img.read(2048))[0].decode())
-    info.tags_load_address = unpack('I', args.boot_img.read(4))[0]
-    info.product_name = cstr(unpack('16s', args.boot_img.read(16))[0].decode())
-    info.header_size = unpack('I', args.boot_img.read(4))[0]
-    info.dtb_size = unpack('I', args.boot_img.read(4))[0]
-    info.dtb_load_address = unpack('Q', args.boot_img.read(8))[0]
+    info.boot_magic = unpack('8s', boot_img.read(8))[0].decode()
+    info.header_version = unpack('I', boot_img.read(4))[0]
+    info.page_size = unpack('I', boot_img.read(4))[0]
+    info.kernel_load_address = unpack('I', boot_img.read(4))[0]
+    info.ramdisk_load_address = unpack('I', boot_img.read(4))[0]
+    info.vendor_ramdisk_size = unpack('I', boot_img.read(4))[0]
+    info.cmdline = cstr(unpack('2048s', boot_img.read(2048))[0].decode())
+    info.tags_load_address = unpack('I', boot_img.read(4))[0]
+    info.product_name = cstr(unpack('16s', boot_img.read(16))[0].decode())
+    info.header_size = unpack('I', boot_img.read(4))[0]
+    info.dtb_size = unpack('I', boot_img.read(4))[0]
+    info.dtb_load_address = unpack('Q', boot_img.read(8))[0]
 
     # Convenient shorthand.
     page_size = info.page_size
@@ -408,10 +408,10 @@
         (ramdisk_offset_base, info.vendor_ramdisk_size, 'vendor_ramdisk'))
 
     if info.header_version > 3:
-        info.vendor_ramdisk_table_size = unpack('I', args.boot_img.read(4))[0]
-        vendor_ramdisk_table_entry_num = unpack('I', args.boot_img.read(4))[0]
-        vendor_ramdisk_table_entry_size = unpack('I', args.boot_img.read(4))[0]
-        info.vendor_bootconfig_size = unpack('I', args.boot_img.read(4))[0]
+        info.vendor_ramdisk_table_size = unpack('I', boot_img.read(4))[0]
+        vendor_ramdisk_table_entry_num = unpack('I', boot_img.read(4))[0]
+        vendor_ramdisk_table_entry_size = unpack('I', boot_img.read(4))[0]
+        info.vendor_bootconfig_size = unpack('I', boot_img.read(4))[0]
         num_vendor_ramdisk_table_pages = get_number_of_pages(
             info.vendor_ramdisk_table_size, page_size)
         vendor_ramdisk_table_offset = page_size * (
@@ -422,16 +422,16 @@
         for idx in range(vendor_ramdisk_table_entry_num):
             entry_offset = vendor_ramdisk_table_offset + (
                 vendor_ramdisk_table_entry_size * idx)
-            args.boot_img.seek(entry_offset)
-            ramdisk_size = unpack('I', args.boot_img.read(4))[0]
-            ramdisk_offset = unpack('I', args.boot_img.read(4))[0]
-            ramdisk_type = unpack('I', args.boot_img.read(4))[0]
+            boot_img.seek(entry_offset)
+            ramdisk_size = unpack('I', boot_img.read(4))[0]
+            ramdisk_offset = unpack('I', boot_img.read(4))[0]
+            ramdisk_type = unpack('I', boot_img.read(4))[0]
             ramdisk_name = cstr(unpack(
                 f'{VENDOR_RAMDISK_NAME_SIZE}s',
-                args.boot_img.read(VENDOR_RAMDISK_NAME_SIZE))[0].decode())
+                boot_img.read(VENDOR_RAMDISK_NAME_SIZE))[0].decode())
             board_id = unpack(
                 f'{VENDOR_RAMDISK_TABLE_ENTRY_BOARD_ID_SIZE}I',
-                args.boot_img.read(
+                boot_img.read(
                     4 * VENDOR_RAMDISK_TABLE_ENTRY_BOARD_ID_SIZE))
             output_ramdisk_name = f'vendor_ramdisk{idx:02}'
 
@@ -455,14 +455,14 @@
     if info.dtb_size > 0:
         image_info_list.append((dtb_offset, info.dtb_size, 'dtb'))
 
-    create_out_dir(args.out)
+    create_out_dir(output_dir)
     for offset, size, name in image_info_list:
-        extract_image(offset, size, args.boot_img, os.path.join(args.out, name))
-    info.image_dir = args.out
+        extract_image(offset, size, boot_img, os.path.join(output_dir, name))
+    info.image_dir = output_dir
 
     if info.header_version > 3:
         vendor_ramdisk_by_name_dir = os.path.join(
-            args.out, 'vendor-ramdisk-by-name')
+            output_dir, 'vendor-ramdisk-by-name')
         create_out_dir(vendor_ramdisk_by_name_dir)
         for src, dst in vendor_ramdisk_symlinks:
             src_pathname = os.path.join('..', src)
@@ -475,19 +475,26 @@
     return info
 
 
-def unpack_image(args):
-    boot_magic = unpack('8s', args.boot_img.read(8))[0].decode()
-    args.boot_img.seek(0)
-    if boot_magic == 'ANDROID!':
-        info = unpack_boot_image(args)
-    elif boot_magic == 'VNDRBOOT':
-        info = unpack_vendor_boot_image(args)
-    else:
-        raise ValueError(f'Not an Android boot image, magic: {boot_magic}')
+def unpack_bootimg(boot_img, output_dir):
+    """Unpacks the |boot_img| to |output_dir|, and returns the 'info' object."""
+    with open(boot_img, 'rb') as image_file:
+        boot_magic = unpack('8s', image_file.read(8))[0].decode()
+        image_file.seek(0)
+        if boot_magic == 'ANDROID!':
+            info = unpack_boot_image(image_file, output_dir)
+        elif boot_magic == 'VNDRBOOT':
+            info = unpack_vendor_boot_image(image_file, output_dir)
+        else:
+            raise ValueError(f'Not an Android boot image, magic: {boot_magic}')
 
-    if args.format == 'mkbootimg':
+    return info
+
+
+def print_bootimg_info(info, output_format, null_separator):
+    """Format and print boot image info."""
+    if output_format == 'mkbootimg':
         mkbootimg_args = info.format_mkbootimg_argument()
-        if args.null:
+        if null_separator:
             print('\0'.join(mkbootimg_args) + '\0', end='')
         else:
             print(shlex.join(mkbootimg_args))
@@ -533,7 +540,7 @@
         description='Unpacks boot, recovery or vendor_boot image.',
         epilog=get_unpack_usage(),
     )
-    parser.add_argument('--boot_img', type=FileType('rb'), required=True,
+    parser.add_argument('--boot_img', required=True,
                         help='path to the boot, recovery or vendor_boot image')
     parser.add_argument('--out', default='out',
                         help='output directory of the unpacked images')
@@ -548,7 +555,8 @@
 def main():
     """parse arguments and unpack boot image"""
     args = parse_cmdline()
-    unpack_image(args)
+    info = unpack_bootimg(args.boot_img, args.out)
+    print_bootimg_info(info, args.format, args.null)
 
 
 if __name__ == '__main__':