xref: /rk3399_rockchip-uboot/scripts/unpack_bootimg (revision 8a334094eed8b1101b3678f75f102162249c5866)
1*8a334094SJoseph Chen#!/usr/bin/env python
2*8a334094SJoseph Chen# Copyright 2018, The Android Open Source Project
3*8a334094SJoseph Chen#
4*8a334094SJoseph Chen# Licensed under the Apache License, Version 2.0 (the "License");
5*8a334094SJoseph Chen# you may not use this file except in compliance with the License.
6*8a334094SJoseph Chen# You may obtain a copy of the License at
7*8a334094SJoseph Chen#
8*8a334094SJoseph Chen#     http://www.apache.org/licenses/LICENSE-2.0
9*8a334094SJoseph Chen#
10*8a334094SJoseph Chen# Unless required by applicable law or agreed to in writing, software
11*8a334094SJoseph Chen# distributed under the License is distributed on an "AS IS" BASIS,
12*8a334094SJoseph Chen# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*8a334094SJoseph Chen# See the License for the specific language governing permissions and
14*8a334094SJoseph Chen# limitations under the License.
15*8a334094SJoseph Chen
16*8a334094SJoseph Chen"""unpacks the bootimage.
17*8a334094SJoseph Chen
18*8a334094SJoseph ChenExtracts the kernel, ramdisk, second bootloader, dtb and recovery dtbo images.
19*8a334094SJoseph Chen"""
20*8a334094SJoseph Chen
21*8a334094SJoseph Chenfrom __future__ import print_function
22*8a334094SJoseph Chenfrom argparse import ArgumentParser, FileType
23*8a334094SJoseph Chenfrom struct import unpack
24*8a334094SJoseph Chenimport os
25*8a334094SJoseph Chen
26*8a334094SJoseph Chen
27*8a334094SJoseph Chendef create_out_dir(dir_path):
28*8a334094SJoseph Chen    """creates a directory 'dir_path' if it does not exist"""
29*8a334094SJoseph Chen    if not os.path.exists(dir_path):
30*8a334094SJoseph Chen        os.makedirs(dir_path)
31*8a334094SJoseph Chen
32*8a334094SJoseph Chen
33*8a334094SJoseph Chendef extract_image(offset, size, bootimage, extracted_image_name):
34*8a334094SJoseph Chen    """extracts an image from the bootimage"""
35*8a334094SJoseph Chen    bootimage.seek(offset)
36*8a334094SJoseph Chen    with open(extracted_image_name, 'wb') as file_out:
37*8a334094SJoseph Chen        file_out.write(bootimage.read(size))
38*8a334094SJoseph Chen
39*8a334094SJoseph Chen
40*8a334094SJoseph Chendef get_number_of_pages(image_size, page_size):
41*8a334094SJoseph Chen    """calculates the number of pages required for the image"""
42*8a334094SJoseph Chen    return (image_size + page_size - 1) / page_size
43*8a334094SJoseph Chen
44*8a334094SJoseph Chen
45*8a334094SJoseph Chendef unpack_bootimage(args):
46*8a334094SJoseph Chen    """extracts kernel, ramdisk, second bootloader and recovery dtbo"""
47*8a334094SJoseph Chen    boot_magic = unpack('8s', args.boot_img.read(8))
48*8a334094SJoseph Chen    print('boot_magic: %s' % boot_magic)
49*8a334094SJoseph Chen    kernel_ramdisk_second_info = unpack('10I', args.boot_img.read(10 * 4))
50*8a334094SJoseph Chen    print('kernel_size: %s' % kernel_ramdisk_second_info[0])
51*8a334094SJoseph Chen    print('kernel load address: %#x' % kernel_ramdisk_second_info[1])
52*8a334094SJoseph Chen    print('ramdisk size: %s' % kernel_ramdisk_second_info[2])
53*8a334094SJoseph Chen    print('ramdisk load address: %#x' % kernel_ramdisk_second_info[3])
54*8a334094SJoseph Chen    print('second bootloader size: %s' % kernel_ramdisk_second_info[4])
55*8a334094SJoseph Chen    print('second bootloader load address: %#x' % kernel_ramdisk_second_info[5])
56*8a334094SJoseph Chen    print('kernel tags load address: %#x' % kernel_ramdisk_second_info[6])
57*8a334094SJoseph Chen    print('page size: %s' % kernel_ramdisk_second_info[7])
58*8a334094SJoseph Chen    print('boot image header version: %s' % kernel_ramdisk_second_info[8])
59*8a334094SJoseph Chen    print('os version and patch level: %s' % kernel_ramdisk_second_info[9])
60*8a334094SJoseph Chen
61*8a334094SJoseph Chen    product_name = unpack('16s', args.boot_img.read(16))
62*8a334094SJoseph Chen    print('product name: %s' % product_name)
63*8a334094SJoseph Chen    cmdline = unpack('512s', args.boot_img.read(512))
64*8a334094SJoseph Chen    print('command line args: %s' % cmdline)
65*8a334094SJoseph Chen
66*8a334094SJoseph Chen    args.boot_img.read(32)  # ignore SHA
67*8a334094SJoseph Chen
68*8a334094SJoseph Chen    extra_cmdline = unpack('1024s', args.boot_img.read(1024))
69*8a334094SJoseph Chen    print('additional command line args: %s' % extra_cmdline)
70*8a334094SJoseph Chen
71*8a334094SJoseph Chen    kernel_size = kernel_ramdisk_second_info[0]
72*8a334094SJoseph Chen    ramdisk_size = kernel_ramdisk_second_info[2]
73*8a334094SJoseph Chen    second_size = kernel_ramdisk_second_info[4]
74*8a334094SJoseph Chen    page_size = kernel_ramdisk_second_info[7]
75*8a334094SJoseph Chen    version = kernel_ramdisk_second_info[8]
76*8a334094SJoseph Chen    if version > 0:
77*8a334094SJoseph Chen        recovery_dtbo_size = unpack('I', args.boot_img.read(1 * 4))[0]
78*8a334094SJoseph Chen        print('recovery dtbo size: %s' % recovery_dtbo_size)
79*8a334094SJoseph Chen        recovery_dtbo_offset = unpack('Q', args.boot_img.read(8))[0]
80*8a334094SJoseph Chen        print('recovery dtbo offset: %#x' % recovery_dtbo_offset)
81*8a334094SJoseph Chen        boot_header_size = unpack('I', args.boot_img.read(4))[0]
82*8a334094SJoseph Chen        print('boot header size: %s' % boot_header_size)
83*8a334094SJoseph Chen    else:
84*8a334094SJoseph Chen        recovery_dtbo_size = 0
85*8a334094SJoseph Chen    if version > 1:
86*8a334094SJoseph Chen        dtb_size = unpack('I', args.boot_img.read(4))[0]
87*8a334094SJoseph Chen        print('dtb size: %s' % dtb_size)
88*8a334094SJoseph Chen        dtb_load_address = unpack('Q', args.boot_img.read(8))[0]
89*8a334094SJoseph Chen        print('dtb address: %#x' % dtb_load_address)
90*8a334094SJoseph Chen    else:
91*8a334094SJoseph Chen        dtb_size = 0
92*8a334094SJoseph Chen
93*8a334094SJoseph Chen
94*8a334094SJoseph Chen    # The first page contains the boot header
95*8a334094SJoseph Chen    num_header_pages = 1
96*8a334094SJoseph Chen
97*8a334094SJoseph Chen    num_kernel_pages = get_number_of_pages(kernel_size, page_size)
98*8a334094SJoseph Chen    kernel_offset = page_size * num_header_pages  # header occupies a page
99*8a334094SJoseph Chen    image_info_list = [(kernel_offset, kernel_size, 'kernel')]
100*8a334094SJoseph Chen
101*8a334094SJoseph Chen    num_ramdisk_pages = get_number_of_pages(ramdisk_size, page_size)
102*8a334094SJoseph Chen    ramdisk_offset = page_size * (num_header_pages + num_kernel_pages
103*8a334094SJoseph Chen                                 ) # header + kernel
104*8a334094SJoseph Chen    image_info_list.append((ramdisk_offset, ramdisk_size, 'ramdisk'))
105*8a334094SJoseph Chen
106*8a334094SJoseph Chen    if second_size > 0:
107*8a334094SJoseph Chen        second_offset = page_size * (
108*8a334094SJoseph Chen                num_header_pages + num_kernel_pages + num_ramdisk_pages
109*8a334094SJoseph Chen                )  # header + kernel + ramdisk
110*8a334094SJoseph Chen        image_info_list.append((second_offset, second_size, 'second'))
111*8a334094SJoseph Chen
112*8a334094SJoseph Chen    if recovery_dtbo_size > 0:
113*8a334094SJoseph Chen        image_info_list.append((recovery_dtbo_offset, recovery_dtbo_size,
114*8a334094SJoseph Chen                                'recovery_dtbo'))
115*8a334094SJoseph Chen    if dtb_size > 0:
116*8a334094SJoseph Chen        num_second_pages = get_number_of_pages(second_size, page_size)
117*8a334094SJoseph Chen        num_recovery_dtbo_pages = get_number_of_pages(recovery_dtbo_size, page_size)
118*8a334094SJoseph Chen        dtb_offset = page_size * (
119*8a334094SJoseph Chen            num_header_pages + num_kernel_pages + num_ramdisk_pages + num_second_pages +
120*8a334094SJoseph Chen            num_recovery_dtbo_pages
121*8a334094SJoseph Chen        )
122*8a334094SJoseph Chen
123*8a334094SJoseph Chen        image_info_list.append((dtb_offset, dtb_size, 'dtb'))
124*8a334094SJoseph Chen
125*8a334094SJoseph Chen    for image_info in image_info_list:
126*8a334094SJoseph Chen        extract_image(image_info[0], image_info[1], args.boot_img,
127*8a334094SJoseph Chen                      os.path.join(args.out, image_info[2]))
128*8a334094SJoseph Chen
129*8a334094SJoseph Chen
130*8a334094SJoseph Chendef parse_cmdline():
131*8a334094SJoseph Chen    """parse command line arguments"""
132*8a334094SJoseph Chen    parser = ArgumentParser(
133*8a334094SJoseph Chen        description='Unpacks boot.img/recovery.img, extracts the kernel,'
134*8a334094SJoseph Chen        'ramdisk, second bootloader, recovery dtbo and dtb')
135*8a334094SJoseph Chen    parser.add_argument(
136*8a334094SJoseph Chen        '--boot_img',
137*8a334094SJoseph Chen        help='path to boot image',
138*8a334094SJoseph Chen        type=FileType('rb'),
139*8a334094SJoseph Chen        required=True)
140*8a334094SJoseph Chen    parser.add_argument('--out', help='path to out binaries', default='out')
141*8a334094SJoseph Chen    return parser.parse_args()
142*8a334094SJoseph Chen
143*8a334094SJoseph Chen
144*8a334094SJoseph Chendef main():
145*8a334094SJoseph Chen    """parse arguments and unpack boot image"""
146*8a334094SJoseph Chen    args = parse_cmdline()
147*8a334094SJoseph Chen    create_out_dir(args.out)
148*8a334094SJoseph Chen    unpack_bootimage(args)
149*8a334094SJoseph Chen
150*8a334094SJoseph Chen
151*8a334094SJoseph Chenif __name__ == '__main__':
152*8a334094SJoseph Chen    main()
153