blob: 6a8ff34538b225e64e9640c915830b0c8e773331 [file] [log] [blame]
Sam Protsenko61c72ea2020-01-24 17:53:45 +02001# SPDX-License-Identifier: GPL-2.0+
2# Copyright (c) 2020
3# Author: Sam Protsenko <joe.skb7@gmail.com>
4
5# Test U-Boot's "abootimg" commands.
6
7import os
8import pytest
9import u_boot_utils
10
11"""
12These tests rely on disk image (boot.img), which is automatically created by
13the test from the stored hex dump. This is done to avoid the dependency on the
14most recent mkbootimg tool from AOSP/master. Here is the list of commands which
15was used to generate the boot.img and obtain compressed hex dump from it:
16
17 $ echo '/dts-v1/; / { model = "x1"; compatible = "y1,z1"; };' > test1.dts
18 $ echo '/dts-v1/; / { model = "x2"; compatible = "y2,z2"; };' > test2.dts
19 $ dtc test1.dts > dt1.dtb
20 $ dtc test2.dts > dt2.dtb
21 $ cat dt1.dtb dt2.dtb > dtb.img
22 $ echo 'kernel payload' > kernel
23 $ echo 'ramdisk payload' > ramdisk.img
24 $ mkbootimg --kernel ./kernel --ramdisk ./ramdisk.img \
25 --cmdline "cmdline test" --dtb ./dtb.img \
26 --os_version R --os_patch_level 2019-06-05 \
27 --header_version 2 --output boot.img
28 $ gzip -9 boot.img
29 $ xxd -p boot.img.gz > boot.img.gz.hex
30
31Now one can obtain original boot.img from this hex dump like this:
32
33 $ xxd -r -p boot.img.gz.hex boot.img.gz
34 $ gunzip -9 boot.img.gz
Safae Ouajihb39cfcb2023-02-06 00:50:20 +010035
36For boot image header version 4, these tests rely on two images that are generated
37using the same steps above :
38
391- boot.img :
40 $ mkbootimg --kernel ./kernel --ramdisk ./ramdisk.img \
41 --cmdline "cmdline test" --dtb ./dtb.img \
42 --os_version R --os_patch_level 2019-06-05 \
43 --header_version 4 --output ./boot.img
44
452- vendor_boot.img
46 $ mkbootimg --kernel ./kernel --ramdisk ./ramdisk.img \
47 --cmdline "cmdline test" --dtb ./dtb.img \
48 --os_version R --os_patch_level 2019-06-05 \
49 --pagesize 4096 --vendor_ramdisk ./ramdisk.img \
50 --header_version 4 --vendor_boot ./vboot.img \
51
Sam Protsenko61c72ea2020-01-24 17:53:45 +020052"""
53
54# boot.img.gz hex dump
55img_hex = """1f8b08084844af5d0203626f6f742e696d670073f47309f2f77451e46700
56820606010106301084501f04181819041838181898803c3346060c909c9b
5792939997aa50925a5cc2300a461c3078b2e1793c4b876fd92db97939fb6c
58b7762ffff07d345446c1281805e8a0868d81e117a45e111c0d8dc101b253
598bf25273140a122b73f21353b8460364148c8251300a46c1281801a02831
603725b3387bb401300a46c1281805a360148c207081f7df5b20550bc41640
619c03c41a0c90f17fe85400986d82452b6c3680198a192a0ce17c3610ae34
62d4a9820881a70f3873f35352731892f3730b124b32937252a96bb9119ae5
63463a5546f82c1f05a360148c8251300a462e000085bf67f200200000"""
Safae Ouajihb39cfcb2023-02-06 00:50:20 +010064
65# boot img v4 hex dump
66boot_img_hex = """1f8b080827b0cd630203626f6f742e696d6700edd8bd0d82601885d1d7c4
6758d8c808b88195bd098d8d246e40e42b083f1aa0717be99d003d277916b8
68e5bddc8a7b792d8e8788c896ce9b88d32ebe6c971e7ddd3543cae734cd01
69c0ffc84c0000b0766d1a87d4e5afeadd3dab7a6f10000000f84163d5d7cd
70d43a000000000000000060c53e7544995700400000"""
71
72# vendor boot image v4 hex dump
73vboot_img_hex = """1f8b0808baaecd63020376626f6f742e696d6700edd8310b824018c6f1b3
74222a08f41b3436b4280dcdd19c11d16ee9109d18d59042d047ec8b04cd0d
75d19d5a4345534bf6ffc173ef29272f38e93b1d0ec67dd79d548462aa1cd2
76d5d20b0000f8438678f90c18d584b8a4bbb3a557991ecb2a0000f80d6b2f
77f4179b656be5c532f2fc066f040000000080e23936af2755f62a3d918df1
78db2a7ab67f9ffdeb7df7cda3465ecb79c4ce7e5c577562bb9364b74449a5
791e467e20c53c0a57de763193c1779b3b4fcd9d4ee27c6a0e00000000c0ff
80309ffea7010000000040f1dc004129855400400000"""
81
Sam Protsenko61c72ea2020-01-24 17:53:45 +020082# Expected response for "abootimg dtb_dump" command
83dtb_dump_resp="""## DTB area contents (concat format):
84 - DTB #0:
85 (DTB)size = 125
86 (DTB)model = x1
87 (DTB)compatible = y1,z1
88 - DTB #1:
89 (DTB)size = 125
90 (DTB)model = x2
91 (DTB)compatible = y2,z2"""
92# Address in RAM where to load the boot image ('abootimg' looks in $loadaddr)
93loadaddr = 0x1000
Safae Ouajihb39cfcb2023-02-06 00:50:20 +010094# Address in RAM where to load the vendor boot image ('abootimg' looks in $vloadaddr)
95vloadaddr= 0x10000
Sam Protsenko61c72ea2020-01-24 17:53:45 +020096# Expected DTB #1 offset from the boot image start address
97dtb1_offset = 0x187d
Safae Ouajihb39cfcb2023-02-06 00:50:20 +010098# Expected DTB offset from the vendor boot image start address
99dtb2_offset = 0x207d
Sam Protsenko61c72ea2020-01-24 17:53:45 +0200100# DTB #1 start address in RAM
101dtb1_addr = loadaddr + dtb1_offset
Safae Ouajihb39cfcb2023-02-06 00:50:20 +0100102# DTB #2 start address in RAM
103dtb2_addr = vloadaddr + dtb2_offset
Sam Protsenko61c72ea2020-01-24 17:53:45 +0200104
105class AbootimgTestDiskImage(object):
106 """Disk image used by abootimg tests."""
107
Safae Ouajihb39cfcb2023-02-06 00:50:20 +0100108 def __init__(self, u_boot_console, image_name, hex_img):
Sam Protsenko61c72ea2020-01-24 17:53:45 +0200109 """Initialize a new AbootimgDiskImage object.
110
111 Args:
112 u_boot_console: A U-Boot console.
113
114 Returns:
115 Nothing.
116 """
117
Safae Ouajihb39cfcb2023-02-06 00:50:20 +0100118 gz_hex = u_boot_console.config.persistent_data_dir + '/' + image_name + '.gz.hex'
119 gz = u_boot_console.config.persistent_data_dir + '/' + image_name + '.gz'
Sam Protsenko61c72ea2020-01-24 17:53:45 +0200120
Safae Ouajihb39cfcb2023-02-06 00:50:20 +0100121 filename = image_name
Sam Protsenko61c72ea2020-01-24 17:53:45 +0200122 persistent = u_boot_console.config.persistent_data_dir + '/' + filename
123 self.path = u_boot_console.config.result_dir + '/' + filename
Safae Ouajihb39cfcb2023-02-06 00:50:20 +0100124 u_boot_console.log.action('persistent is ' + persistent)
Sam Protsenko61c72ea2020-01-24 17:53:45 +0200125 with u_boot_utils.persistent_file_helper(u_boot_console.log, persistent):
126 if os.path.exists(persistent):
127 u_boot_console.log.action('Disk image file ' + persistent +
128 ' already exists')
129 else:
130 u_boot_console.log.action('Generating ' + persistent)
131
132 f = open(gz_hex, "w")
Safae Ouajihb39cfcb2023-02-06 00:50:20 +0100133 f.write(hex_img)
Sam Protsenko61c72ea2020-01-24 17:53:45 +0200134 f.close()
Sam Protsenko61c72ea2020-01-24 17:53:45 +0200135 cmd = ('xxd', '-r', '-p', gz_hex, gz)
136 u_boot_utils.run_and_log(u_boot_console, cmd)
Sam Protsenko61c72ea2020-01-24 17:53:45 +0200137 cmd = ('gunzip', '-9', gz)
138 u_boot_utils.run_and_log(u_boot_console, cmd)
139
140 cmd = ('cp', persistent, self.path)
141 u_boot_utils.run_and_log(u_boot_console, cmd)
142
Safae Ouajihb39cfcb2023-02-06 00:50:20 +0100143gtdi1 = None
Sam Protsenko61c72ea2020-01-24 17:53:45 +0200144@pytest.fixture(scope='function')
145def abootimg_disk_image(u_boot_console):
146 """pytest fixture to provide a AbootimgTestDiskImage object to tests.
147 This is function-scoped because it uses u_boot_console, which is also
148 function-scoped. However, we don't need to actually do any function-scope
149 work, so this simply returns the same object over and over each time."""
150
Safae Ouajihb39cfcb2023-02-06 00:50:20 +0100151 global gtdi1
152 if not gtdi1:
153 gtdi1 = AbootimgTestDiskImage(u_boot_console, 'boot.img', img_hex)
154 return gtdi1
155
156gtdi2 = None
157@pytest.fixture(scope='function')
158def abootimgv4_disk_image_vboot(u_boot_console):
159 """pytest fixture to provide a AbootimgTestDiskImage object to tests.
160 This is function-scoped because it uses u_boot_console, which is also
161 function-scoped. However, we don't need to actually do any function-scope
162 work, so this simply returns the same object over and over each time."""
163
164 global gtdi2
165 if not gtdi2:
166 gtdi2 = AbootimgTestDiskImage(u_boot_console, 'vendor_boot.img', vboot_img_hex)
167 return gtdi2
168
169gtdi3 = None
170@pytest.fixture(scope='function')
171def abootimgv4_disk_image_boot(u_boot_console):
172 """pytest fixture to provide a AbootimgTestDiskImage object to tests.
173 This is function-scoped because it uses u_boot_console, which is also
174 function-scoped. However, we don't need to actually do any function-scope
175 work, so this simply returns the same object over and over each time."""
176
177 global gtdi3
178 if not gtdi3:
179 gtdi3 = AbootimgTestDiskImage(u_boot_console, 'bootv4.img', boot_img_hex)
180 return gtdi3
Sam Protsenko61c72ea2020-01-24 17:53:45 +0200181
182@pytest.mark.boardspec('sandbox')
183@pytest.mark.buildconfigspec('android_boot_image')
184@pytest.mark.buildconfigspec('cmd_abootimg')
185@pytest.mark.buildconfigspec('cmd_fdt')
186@pytest.mark.requiredtool('xxd')
187@pytest.mark.requiredtool('gunzip')
188def test_abootimg(abootimg_disk_image, u_boot_console):
189 """Test the 'abootimg' command."""
190
191 u_boot_console.log.action('Loading disk image to RAM...')
192 u_boot_console.run_command('setenv loadaddr 0x%x' % (loadaddr))
193 u_boot_console.run_command('host load hostfs - 0x%x %s' % (loadaddr,
194 abootimg_disk_image.path))
195
196 u_boot_console.log.action('Testing \'abootimg get ver\'...')
197 response = u_boot_console.run_command('abootimg get ver')
198 assert response == "2"
199 u_boot_console.run_command('abootimg get ver v')
200 response = u_boot_console.run_command('env print v')
201 assert response == 'v=2'
202
203 u_boot_console.log.action('Testing \'abootimg get recovery_dtbo\'...')
204 response = u_boot_console.run_command('abootimg get recovery_dtbo a')
205 assert response == 'Error: recovery_dtbo_size is 0'
206
207 u_boot_console.log.action('Testing \'abootimg dump dtb\'...')
208 response = u_boot_console.run_command('abootimg dump dtb').replace('\r', '')
209 assert response == dtb_dump_resp
210
211 u_boot_console.log.action('Testing \'abootimg get dtb_load_addr\'...')
212 u_boot_console.run_command('abootimg get dtb_load_addr a')
213 response = u_boot_console.run_command('env print a')
214 assert response == 'a=11f00000'
215
216 u_boot_console.log.action('Testing \'abootimg get dtb --index\'...')
217 u_boot_console.run_command('abootimg get dtb --index=1 dtb1_start')
218 response = u_boot_console.run_command('env print dtb1_start')
219 correct_str = "dtb1_start=%x" % (dtb1_addr)
220 assert response == correct_str
221 u_boot_console.run_command('fdt addr $dtb1_start')
222 u_boot_console.run_command('fdt get value v / model')
223 response = u_boot_console.run_command('env print v')
224 assert response == 'v=x2'
Safae Ouajihb39cfcb2023-02-06 00:50:20 +0100225
226@pytest.mark.boardspec('sandbox')
227@pytest.mark.buildconfigspec('android_boot_image')
228@pytest.mark.buildconfigspec('cmd_abootimg')
229@pytest.mark.buildconfigspec('cmd_fdt')
230@pytest.mark.requiredtool('xxd')
231@pytest.mark.requiredtool('gunzip')
232def test_abootimgv4(abootimgv4_disk_image_vboot, abootimgv4_disk_image_boot, u_boot_console):
233 """Test the 'abootimg' command with boot image header v4."""
234
235 cons = u_boot_console
236 cons.log.action('Loading disk image to RAM...')
237 cons.run_command('setenv loadaddr 0x%x' % (loadaddr))
238 cons.run_command('setenv vloadaddr 0x%x' % (vloadaddr))
239 cons.run_command('host load hostfs - 0x%x %s' % (vloadaddr,
240 abootimgv4_disk_image_vboot.path))
241 cons.run_command('host load hostfs - 0x%x %s' % (loadaddr,
242 abootimgv4_disk_image_boot.path))
243 cons.run_command('abootimg addr 0x%x 0x%x' % (loadaddr, vloadaddr))
244 cons.log.action('Testing \'abootimg get ver\'...')
245 response = cons.run_command('abootimg get ver')
246 assert response == "4"
247 cons.run_command('abootimg get ver v')
248 response = cons.run_command('env print v')
249 assert response == 'v=4'
250
251 cons.log.action('Testing \'abootimg get recovery_dtbo\'...')
252 response = cons.run_command('abootimg get recovery_dtbo a')
253 assert response == 'Error: header version must be >= 1 and <= 2 to get dtbo'
254
255 cons.log.action('Testing \'abootimg get dtb_load_addr\'...')
256 cons.run_command('abootimg get dtb_load_addr a')
257 response = cons.run_command('env print a')
258 assert response == 'a=11f00000'
259
260 cons.log.action('Testing \'abootimg get dtb --index\'...')
261 cons.run_command('abootimg get dtb --index=1 dtb2_start')
262 response = cons.run_command('env print dtb2_start')
263 correct_str = "dtb2_start=%x" % (dtb2_addr)
264 assert response == correct_str
265
266 cons.run_command('fdt addr $dtb2_start')
267 cons.run_command('fdt get value v / model')
268 response = cons.run_command('env print v')
269 assert response == 'v=x2'