blob: d7d74356928e2a754f26c3cb05f691e706acbcec [file] [log] [blame]
Love Kumarb2835c52024-06-05 15:19:35 +05301# SPDX-License-Identifier: GPL-2.0
2# (C) Copyright 2023, Advanced Micro Devices, Inc.
3
4import pytest
5import u_boot_utils
6import test_net
7import re
8
9"""
10Note: This test relies on boardenv_* containing configuration values to define
11which the network environment available for testing. Without this, this test
12will be automatically skipped.
13
14For example:
15
16# Details regarding a boot image file that may be read from a TFTP server. This
17# variable may be omitted or set to None if TFTP boot testing is not possible
18# or desired.
19env__net_tftp_bootable_file = {
20 'fn': 'image.ub',
21 'addr': 0x10000000,
22 'size': 5058624,
23 'crc32': 'c2244b26',
24 'pattern': 'Linux',
25 'config': 'config@2',
26 'timeout': 50000,
27 'check_type': 'boot_error',
28 'check_pattern': 'ERROR',
29}
30
31# False or omitted if a TFTP boot test should be tested.
32# If TFTP boot testing is not possible or desired, set this variable to True.
33# For example: If FIT image is not proper to boot
34env__tftp_boot_test_skip = False
35
36# Here is the example of FIT image configurations:
37configurations {
38 default = "config@1";
39 config@1 {
40 description = "Boot Linux kernel with config@1";
41 kernel = "kernel@0";
42 fdt = "fdt@0";
43 ramdisk = "ramdisk@0";
44 hash@1 {
45 algo = "sha1";
46 };
47 };
48 config@2 {
49 description = "Boot Linux kernel with config@2";
50 kernel = "kernel@1";
51 fdt = "fdt@1";
52 ramdisk = "ramdisk@1";
53 hash@1 {
54 algo = "sha1";
55 };
56 };
57};
58
59# Details regarding a file that may be read from a TFTP server. This variable
60# may be omitted or set to None if PXE testing is not possible or desired.
61env__net_pxe_bootable_file = {
62 'fn': 'default',
63 'addr': 0x10000000,
64 'size': 74,
65 'timeout': 50000,
66 'pattern': 'Linux',
67 'valid_label': '1',
68 'invalid_label': '2',
69 'exp_str_invalid': 'Skipping install for failure retrieving',
70 'local_label': '3',
71 'exp_str_local': 'missing environment variable: localcmd',
72 'empty_label': '4',
73 'exp_str_empty': 'No kernel given, skipping boot',
74 'check_type': 'boot_error',
75 'check_pattern': 'ERROR',
76}
77
Jerome Forissier9f050992024-09-11 11:58:24 +020078# False if a PXE boot test should be tested.
Love Kumarb2835c52024-06-05 15:19:35 +053079# If PXE boot testing is not possible or desired, set this variable to True.
80# For example: If pxe configuration file is not proper to boot
81env__pxe_boot_test_skip = False
82
83# Here is the example of pxe configuration file ordered based on the execution
84# flow:
851) /tftpboot/pxelinux.cfg/default-arm-zynqmp
86
87 menu include pxelinux.cfg/default-arm
88 timeout 50
89
90 default Linux
91
922) /tftpboot/pxelinux.cfg/default-arm
93
94 menu title Linux boot selections
95 menu include pxelinux.cfg/default
96
97 label install
98 menu label Invalid boot
99 kernel kernels/install.bin
100 append console=ttyAMA0,38400 debug earlyprintk
101 initrd initrds/uzInitrdDebInstall
102
103 label local
104 menu label Local boot
105 append root=/dev/sdb1
106 localboot 1
107
108 label boot
109 menu label Empty boot
110
1113) /tftpboot/pxelinux.cfg/default
112
113 label Linux
114 menu label Boot kernel
115 kernel Image
116 fdt system.dtb
117 initrd rootfs.cpio.gz.u-boot
118"""
119
120def setup_networking(u_boot_console):
121 test_net.test_net_dhcp(u_boot_console)
122 if not test_net.net_set_up:
123 test_net.test_net_setup_static(u_boot_console)
124
125def setup_tftpboot_boot(u_boot_console):
126 f = u_boot_console.config.env.get('env__net_tftp_bootable_file', None)
127 if not f:
128 pytest.skip('No TFTP bootable file to read')
129
130 setup_networking(u_boot_console)
131 addr = f.get('addr', None)
132 if not addr:
133 addr = u_boot_utils.find_ram_base(u_boot_console)
134
135 fn = f['fn']
136 timeout = f.get('timeout', 50000)
137
138 with u_boot_console.temporary_timeout(timeout):
139 output = u_boot_console.run_command('tftpboot %x %s' % (addr, fn))
140
141 expected_text = 'Bytes transferred = '
142 sz = f.get('size', None)
143 if sz:
144 expected_text += '%d' % sz
145 assert expected_text in output
146
147 expected_crc = f.get('crc32', None)
148 output = u_boot_console.run_command('crc32 %x $filesize' % addr)
149 if expected_crc:
150 assert expected_crc in output
151
152 pattern = f.get('pattern')
153 chk_type = f.get('check_type', 'boot_error')
154 chk_pattern = re.compile(f.get('check_pattern', 'ERROR'))
155 config = f.get('config', None)
156
157 return addr, timeout, pattern, chk_type, chk_pattern, config
158
Tom Rini5568cc32024-06-18 14:23:43 -0600159@pytest.mark.buildconfigspec('cmd_tftpboot')
Love Kumarb2835c52024-06-05 15:19:35 +0530160def test_net_tftpboot_boot(u_boot_console):
161 """Boot the loaded image
162
163 A boot file (fit image) is downloaded from the TFTP server and booted using
164 bootm command with the default fit configuration, its boot log pattern are
165 validated.
166
167 The details of the file to download are provided by the boardenv_* file;
168 see the comment at the beginning of this file.
169 """
170 if u_boot_console.config.env.get('env__tftp_boot_test_skip', True):
171 pytest.skip('TFTP boot test is not enabled!')
172
173 addr, timeout, pattern, chk_type, chk_pattern, imcfg = setup_tftpboot_boot(
174 u_boot_console
175 )
176
177 if imcfg:
178 bootcmd = 'bootm %x#%s' % (addr, imcfg)
179 else:
180 bootcmd = 'bootm %x' % addr
181
182 with u_boot_console.enable_check(
183 chk_type, chk_pattern
184 ), u_boot_console.temporary_timeout(timeout):
185 try:
186 # wait_for_prompt=False makes the core code not wait for the U-Boot
187 # prompt code to be seen, since it won't be on a successful kernel
188 # boot
189 u_boot_console.run_command(bootcmd, wait_for_prompt=False)
190
191 # Wait for boot log pattern
192 u_boot_console.wait_for(pattern)
193 finally:
194 # This forces the console object to be shutdown, so any subsequent
195 # test will reset the board back into U-Boot. We want to force this
196 # no matter whether the kernel boot passed or failed.
197 u_boot_console.drain_console()
198 u_boot_console.cleanup_spawn()
199
200def setup_pxe_boot(u_boot_console):
201 f = u_boot_console.config.env.get('env__net_pxe_bootable_file', None)
202 if not f:
203 pytest.skip('No PXE bootable file to read')
204
205 setup_networking(u_boot_console)
206 bootfile = u_boot_console.run_command('echo $bootfile')
207 if not bootfile:
208 bootfile = '<NULL>'
209
210 return f, bootfile
211
Love Kumarb2835c52024-06-05 15:19:35 +0530212@pytest.mark.buildconfigspec('cmd_pxe')
213def test_net_pxe_boot(u_boot_console):
214 """Test the pxe boot command.
215
216 A pxe configuration file is downloaded from the TFTP server and interpreted
217 to boot the images mentioned in pxe configuration file.
218
219 The details of the file to download are provided by the boardenv_* file;
220 see the comment at the beginning of this file.
221 """
222 if u_boot_console.config.env.get('env__pxe_boot_test_skip', True):
223 pytest.skip('PXE boot test is not enabled!')
224
225 f, bootfile = setup_pxe_boot(u_boot_console)
226 addr = f.get('addr', None)
227 timeout = f.get('timeout', u_boot_console.p.timeout)
228 fn = f['fn']
229
230 if addr:
231 u_boot_console.run_command('setenv pxefile_addr_r %x' % addr)
232
233 with u_boot_console.temporary_timeout(timeout):
234 output = u_boot_console.run_command('pxe get')
235
236 expected_text = 'Bytes transferred = '
237 sz = f.get('size', None)
238 if sz:
239 expected_text += '%d' % sz
240 assert 'TIMEOUT' not in output
241 assert expected_text in output
242 assert f"Config file '{bootfile}' found" in output
243
244 pattern = f.get('pattern')
245 chk_type = f.get('check_type', 'boot_error')
246 chk_pattern = re.compile(f.get('check_pattern', 'ERROR'))
247
248 if not addr:
249 pxe_boot_cmd = 'pxe boot'
250 else:
251 pxe_boot_cmd = 'pxe boot %x' % addr
252
253 with u_boot_console.enable_check(
254 chk_type, chk_pattern
255 ), u_boot_console.temporary_timeout(timeout):
256 try:
257 u_boot_console.run_command(pxe_boot_cmd, wait_for_prompt=False)
258 u_boot_console.wait_for(pattern)
259 finally:
260 u_boot_console.drain_console()
261 u_boot_console.cleanup_spawn()
262
Love Kumarb2835c52024-06-05 15:19:35 +0530263@pytest.mark.buildconfigspec('cmd_pxe')
264def test_net_pxe_boot_config(u_boot_console):
265 """Test the pxe boot command by selecting different combination of labels
266
267 A pxe configuration file is downloaded from the TFTP server and interpreted
268 to boot the images mentioned in pxe configuration file.
269
270 The details of the file to download are provided by the boardenv_* file;
271 see the comment at the beginning of this file.
272 """
273 if u_boot_console.config.env.get('env__pxe_boot_test_skip', True):
274 pytest.skip('PXE boot test is not enabled!')
275
276 f, bootfile = setup_pxe_boot(u_boot_console)
277 addr = f.get('addr', None)
278 timeout = f.get('timeout', u_boot_console.p.timeout)
279 fn = f['fn']
280 local_label = f['local_label']
281 empty_label = f['empty_label']
282 exp_str_local = f['exp_str_local']
283 exp_str_empty = f['exp_str_empty']
284
285 if addr:
286 u_boot_console.run_command('setenv pxefile_addr_r %x' % addr)
287
288 with u_boot_console.temporary_timeout(timeout):
289 output = u_boot_console.run_command('pxe get')
290
291 expected_text = 'Bytes transferred = '
292 sz = f.get('size', None)
293 if sz:
294 expected_text += '%d' % sz
295 assert 'TIMEOUT' not in output
296 assert expected_text in output
297 assert f"Config file '{bootfile}' found" in output
298
299 pattern = f.get('pattern')
300 chk_type = f.get('check_type', 'boot_error')
301 chk_pattern = re.compile(f.get('check_pattern', 'ERROR'))
302
303 if not addr:
304 pxe_boot_cmd = 'pxe boot'
305 else:
306 pxe_boot_cmd = 'pxe boot %x' % addr
307
308 with u_boot_console.enable_check(
309 chk_type, chk_pattern
310 ), u_boot_console.temporary_timeout(timeout):
311 try:
312 u_boot_console.run_command(pxe_boot_cmd, wait_for_prompt=False)
313
314 # pxe config is loaded where multiple labels are there and need to
315 # select particular label to boot and check for expected string
316 # In this case, local label is selected and it should look for
317 # localcmd env variable and if that variable is not defined it
318 # should not boot it and come out to u-boot prompt
319 u_boot_console.wait_for('Enter choice:')
320 u_boot_console.run_command(local_label, wait_for_prompt=False)
321 expected_str = u_boot_console.p.expect([exp_str_local])
322 assert (
323 expected_str == 0
324 ), f'Expected string: {exp_str_local} did not match!'
325
326 # In this case, empty label is selected and it should look for
327 # kernel image path and if it is not set it should fail it and load
328 # default label to boot
329 u_boot_console.run_command(pxe_boot_cmd, wait_for_prompt=False)
330 u_boot_console.wait_for('Enter choice:')
331 u_boot_console.run_command(empty_label, wait_for_prompt=False)
332 expected_str = u_boot_console.p.expect([exp_str_empty])
333 assert (
334 expected_str == 0
335 ), f'Expected string: {exp_str_empty} did not match!'
336
337 u_boot_console.wait_for(pattern)
338 finally:
339 u_boot_console.drain_console()
340 u_boot_console.cleanup_spawn()
341
Love Kumarb2835c52024-06-05 15:19:35 +0530342@pytest.mark.buildconfigspec('cmd_pxe')
343def test_net_pxe_boot_config_invalid(u_boot_console):
344 """Test the pxe boot command by selecting invalid label
345
346 A pxe configuration file is downloaded from the TFTP server and interpreted
347 to boot the images mentioned in pxe configuration file.
348
349 The details of the file to download are provided by the boardenv_* file;
350 see the comment at the beginning of this file.
351 """
352 if u_boot_console.config.env.get('env__pxe_boot_test_skip', True):
353 pytest.skip('PXE boot test is not enabled!')
354
355 f, bootfile = setup_pxe_boot(u_boot_console)
356 addr = f.get('addr', None)
357 timeout = f.get('timeout', u_boot_console.p.timeout)
358 fn = f['fn']
359 invalid_label = f['invalid_label']
360 exp_str_invalid = f['exp_str_invalid']
361
362 if addr:
363 u_boot_console.run_command('setenv pxefile_addr_r %x' % addr)
364
365 with u_boot_console.temporary_timeout(timeout):
366 output = u_boot_console.run_command('pxe get')
367
368 expected_text = 'Bytes transferred = '
369 sz = f.get('size', None)
370 if sz:
371 expected_text += '%d' % sz
372 assert 'TIMEOUT' not in output
373 assert expected_text in output
374 assert f"Config file '{bootfile}' found" in output
375
376 pattern = f.get('pattern')
377 if not addr:
378 pxe_boot_cmd = 'pxe boot'
379 else:
380 pxe_boot_cmd = 'pxe boot %x' % addr
381
382 with u_boot_console.temporary_timeout(timeout):
383 try:
384 u_boot_console.run_command(pxe_boot_cmd, wait_for_prompt=False)
385
386 # pxe config is loaded where multiple labels are there and need to
387 # select particular label to boot and check for expected string
388 # In this case invalid label is selected, it should load invalid
389 # label and if it fails it should load the default label to boot
390 u_boot_console.wait_for('Enter choice:')
391 u_boot_console.run_command(invalid_label, wait_for_prompt=False)
392 expected_str = u_boot_console.p.expect([exp_str_invalid])
393 assert (
394 expected_str == 0
395 ), f'Expected string: {exp_str_invalid} did not match!'
396
397 u_boot_console.wait_for(pattern)
398 finally:
399 u_boot_console.drain_console()
400 u_boot_console.cleanup_spawn()