blob: 6e135b663e861f5c69645fc4903c84cc0468e7f6 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001# SPDX-License-Identifier: GPL-2.0
Alison Chaiken1b11fb02017-09-09 23:47:13 -07002# Copyright (c) 2017 Alison Chaiken
Stephen Warren97dcbde2017-09-15 12:19:38 -06003# Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved.
Alison Chaiken1b11fb02017-09-09 23:47:13 -07004
5# Test GPT manipulation commands.
6
7import os
8import pytest
9import u_boot_utils
Alison Chaiken1b11fb02017-09-09 23:47:13 -070010
11"""
Stephen Warren97dcbde2017-09-15 12:19:38 -060012These tests rely on a 4 MB disk image, which is automatically created by
13the test.
Alison Chaiken1b11fb02017-09-09 23:47:13 -070014"""
15
Simon Glassdddd0772022-08-06 17:51:53 -060016# Mark all tests here as slow
17pytestmark = pytest.mark.slow
18
Joshua Wattda401732023-08-31 10:51:39 -060019def parse_gpt_parts(disk_str):
20 """Parser a partition string into a list of partitions.
21
22 Args:
23 disk_str: The disk description string, as returned by `gpt read`
24
25 Returns:
26 A list of parsed partitions. Each partition is a dictionary with the
27 string value from each specified key in the partition description, or a
28 key with with the value True for a boolean flag
29 """
30 parts = []
31 for part_str in disk_str.split(';'):
32 part = {}
33 for option in part_str.split(","):
34 if not option:
35 continue
36
37 if "=" in option:
38 key, value = option.split("=")
39 part[key] = value
40 else:
41 part[option] = True
42
43 if part:
44 parts.append(part)
45
46 return parts
47
Stephen Warren97dcbde2017-09-15 12:19:38 -060048class GptTestDiskImage(object):
49 """Disk Image used by the GPT tests."""
50
51 def __init__(self, u_boot_console):
52 """Initialize a new GptTestDiskImage object.
53
54 Args:
55 u_boot_console: A U-Boot console.
56
57 Returns:
58 Nothing.
59 """
60
61 filename = 'test_gpt_disk_image.bin'
Stephen Warren97dcbde2017-09-15 12:19:38 -060062
Patrick Delaunaye9e3a3e2017-10-18 15:11:03 +020063 persistent = u_boot_console.config.persistent_data_dir + '/' + filename
64 self.path = u_boot_console.config.result_dir + '/' + filename
65
Stephen Warrena3b8f992017-10-26 18:23:35 -060066 with u_boot_utils.persistent_file_helper(u_boot_console.log, persistent):
67 if os.path.exists(persistent):
68 u_boot_console.log.action('Disk image file ' + persistent +
69 ' already exists')
70 else:
71 u_boot_console.log.action('Generating ' + persistent)
72 fd = os.open(persistent, os.O_RDWR | os.O_CREAT)
73 os.ftruncate(fd, 4194304)
74 os.close(fd)
Sam Protsenko13616a92019-07-02 21:20:32 +030075 cmd = ('sgdisk',
76 '--disk-guid=375a56f7-d6c9-4e81-b5f0-09d41ca89efe',
Stephen Warrena3b8f992017-10-26 18:23:35 -060077 persistent)
78 u_boot_utils.run_and_log(u_boot_console, cmd)
Patrick Delaunayde7200a2017-12-06 18:08:20 +010079 # part1 offset 1MB size 1MB
Sam Protsenko13616a92019-07-02 21:20:32 +030080 cmd = ('sgdisk', '--new=1:2048:4095', '--change-name=1:part1',
Joshua Wattda401732023-08-31 10:51:39 -060081 '--partition-guid=1:33194895-67f6-4561-8457-6fdeed4f50a3',
Joshua Wattfd1134e2023-08-31 10:51:37 -060082 '-A 1:set:2',
Sam Protsenko13616a92019-07-02 21:20:32 +030083 persistent)
Patrick Delaunayde7200a2017-12-06 18:08:20 +010084 # part2 offset 2MB size 1.5MB
Stephen Warrena3b8f992017-10-26 18:23:35 -060085 u_boot_utils.run_and_log(u_boot_console, cmd)
Sam Protsenko13616a92019-07-02 21:20:32 +030086 cmd = ('sgdisk', '--new=2:4096:7167', '--change-name=2:part2',
Joshua Wattda401732023-08-31 10:51:39 -060087 '--partition-guid=2:cc9c6e4a-6551-4cb5-87be-3210f96c86fb',
Sam Protsenko13616a92019-07-02 21:20:32 +030088 persistent)
Stephen Warrena3b8f992017-10-26 18:23:35 -060089 u_boot_utils.run_and_log(u_boot_console, cmd)
Sam Protsenko13616a92019-07-02 21:20:32 +030090 cmd = ('sgdisk', '--load-backup=' + persistent)
Stephen Warrena3b8f992017-10-26 18:23:35 -060091 u_boot_utils.run_and_log(u_boot_console, cmd)
Stephen Warren97dcbde2017-09-15 12:19:38 -060092
Patrick Delaunaye9e3a3e2017-10-18 15:11:03 +020093 cmd = ('cp', persistent, self.path)
94 u_boot_utils.run_and_log(u_boot_console, cmd)
95
Stephen Warren97dcbde2017-09-15 12:19:38 -060096@pytest.fixture(scope='function')
97def state_disk_image(u_boot_console):
98 """pytest fixture to provide a GptTestDiskImage object to tests.
99 This is function-scoped because it uses u_boot_console, which is also
Joshua Wattd64d5792023-08-31 10:51:36 -0600100 function-scoped. A new disk is returned each time to prevent tests from
101 interfering with each other."""
Stephen Warren97dcbde2017-09-15 12:19:38 -0600102
Joshua Wattd64d5792023-08-31 10:51:36 -0600103 return GptTestDiskImage(u_boot_console)
Stephen Warren97dcbde2017-09-15 12:19:38 -0600104
105@pytest.mark.boardspec('sandbox')
Alison Chaiken1b11fb02017-09-09 23:47:13 -0700106@pytest.mark.buildconfigspec('cmd_gpt')
Patrick Delaunayc06b7842017-10-18 15:11:04 +0200107@pytest.mark.buildconfigspec('cmd_part')
108@pytest.mark.requiredtool('sgdisk')
109def test_gpt_read(state_disk_image, u_boot_console):
110 """Test the gpt read command."""
111
112 u_boot_console.run_command('host bind 0 ' + state_disk_image.path)
113 output = u_boot_console.run_command('gpt read host 0')
Patrick Delaunayde7200a2017-12-06 18:08:20 +0100114 assert 'Start 1MiB, size 1MiB' in output
Patrick Delaunayc06b7842017-10-18 15:11:04 +0200115 assert 'Block size 512, name part1' in output
Patrick Delaunayde7200a2017-12-06 18:08:20 +0100116 assert 'Start 2MiB, size 1MiB' in output
Patrick Delaunayc06b7842017-10-18 15:11:04 +0200117 assert 'Block size 512, name part2' in output
118 output = u_boot_console.run_command('part list host 0')
Patrick Delaunayde7200a2017-12-06 18:08:20 +0100119 assert '0x00000800 0x00000fff "part1"' in output
120 assert '0x00001000 0x00001bff "part2"' in output
Patrick Delaunayc06b7842017-10-18 15:11:04 +0200121
122@pytest.mark.boardspec('sandbox')
123@pytest.mark.buildconfigspec('cmd_gpt')
Joshua Wattda401732023-08-31 10:51:39 -0600124@pytest.mark.buildconfigspec('partition_type_guid')
125@pytest.mark.requiredtool('sgdisk')
126def test_gpt_read_var(state_disk_image, u_boot_console):
127 """Test the gpt read command."""
128
129 u_boot_console.run_command('host bind 0 ' + state_disk_image.path)
130 output = u_boot_console.run_command('gpt read host 0 gpt_parts')
131 assert 'success!' in output
132
133 output = u_boot_console.run_command('echo ${gpt_parts}')
134 parts = parse_gpt_parts(output.rstrip())
135
136 assert parts == [
137 {
138 "uuid_disk": "375a56f7-d6c9-4e81-b5f0-09d41ca89efe",
139 },
140 {
141 "name": "part1",
142 "start": "0x100000",
143 "size": "0x100000",
144 "type": "0fc63daf-8483-4772-8e79-3d69d8477de4",
145 "uuid": "33194895-67f6-4561-8457-6fdeed4f50a3",
Joshua Watt9e58adf2023-08-31 10:51:40 -0600146 "bootable": True,
Joshua Wattda401732023-08-31 10:51:39 -0600147 },
148 {
149 "name": "part2",
150 "start": "0x200000",
151 "size": "0x180000",
152 "type": "0fc63daf-8483-4772-8e79-3d69d8477de4",
153 "uuid": "cc9c6e4a-6551-4cb5-87be-3210f96c86fb",
154 },
155 ]
156
157@pytest.mark.boardspec('sandbox')
158@pytest.mark.buildconfigspec('cmd_gpt')
Patrick Delaunayc06b7842017-10-18 15:11:04 +0200159@pytest.mark.requiredtool('sgdisk')
160def test_gpt_verify(state_disk_image, u_boot_console):
161 """Test the gpt verify command."""
162
163 u_boot_console.run_command('host bind 0 ' + state_disk_image.path)
164 output = u_boot_console.run_command('gpt verify host 0')
165 assert 'Verify GPT: success!' in output
166
167@pytest.mark.boardspec('sandbox')
168@pytest.mark.buildconfigspec('cmd_gpt')
Stephen Warren2079db32017-09-18 11:11:49 -0600169@pytest.mark.requiredtool('sgdisk')
Philippe Reynesdbeedc32022-04-22 17:46:50 +0200170def test_gpt_repair(state_disk_image, u_boot_console):
171 """Test the gpt repair command."""
172
173 u_boot_console.run_command('host bind 0 ' + state_disk_image.path)
174 output = u_boot_console.run_command('gpt repair host 0')
175 assert 'Repairing GPT: success!' in output
176
177@pytest.mark.boardspec('sandbox')
178@pytest.mark.buildconfigspec('cmd_gpt')
179@pytest.mark.requiredtool('sgdisk')
Stephen Warren97dcbde2017-09-15 12:19:38 -0600180def test_gpt_guid(state_disk_image, u_boot_console):
Alison Chaiken1b11fb02017-09-09 23:47:13 -0700181 """Test the gpt guid command."""
182
Stephen Warren97dcbde2017-09-15 12:19:38 -0600183 u_boot_console.run_command('host bind 0 ' + state_disk_image.path)
Alison Chaiken1b11fb02017-09-09 23:47:13 -0700184 output = u_boot_console.run_command('gpt guid host 0')
185 assert '375a56f7-d6c9-4e81-b5f0-09d41ca89efe' in output
186
Stephen Warren97dcbde2017-09-15 12:19:38 -0600187@pytest.mark.boardspec('sandbox')
Alison Chaiken1b11fb02017-09-09 23:47:13 -0700188@pytest.mark.buildconfigspec('cmd_gpt')
Stephen Warren2079db32017-09-18 11:11:49 -0600189@pytest.mark.requiredtool('sgdisk')
Joshua Wattfd1134e2023-08-31 10:51:37 -0600190def test_gpt_setenv(state_disk_image, u_boot_console):
191 """Test the gpt setenv command."""
192 u_boot_console.run_command('host bind 0 ' + state_disk_image.path)
193 output = u_boot_console.run_command('gpt setenv host 0 part1')
194 assert 'success!' in output
195 output = u_boot_console.run_command('echo ${gpt_partition_addr}')
196 assert output.rstrip() == '800'
197 output = u_boot_console.run_command('echo ${gpt_partition_size}')
198 assert output.rstrip() == '800'
199 output = u_boot_console.run_command('echo ${gpt_partition_name}')
200 assert output.rstrip() == 'part1'
201 output = u_boot_console.run_command('echo ${gpt_partition_entry}')
202 assert output.rstrip() == '1'
203 output = u_boot_console.run_command('echo ${gpt_partition_bootable}')
204 assert output.rstrip() == '1'
205
206 output = u_boot_console.run_command('gpt setenv host 0 part2')
207 assert 'success!' in output
208 output = u_boot_console.run_command('echo ${gpt_partition_addr}')
209 assert output.rstrip() == '1000'
210 output = u_boot_console.run_command('echo ${gpt_partition_size}')
211 assert output.rstrip() == 'c00'
212 output = u_boot_console.run_command('echo ${gpt_partition_name}')
213 assert output.rstrip() == 'part2'
214 output = u_boot_console.run_command('echo ${gpt_partition_entry}')
215 assert output.rstrip() == '2'
216 output = u_boot_console.run_command('echo ${gpt_partition_bootable}')
217 assert output.rstrip() == '0'
218
219@pytest.mark.boardspec('sandbox')
220@pytest.mark.buildconfigspec('cmd_gpt')
221@pytest.mark.requiredtool('sgdisk')
Stephen Warren97dcbde2017-09-15 12:19:38 -0600222def test_gpt_save_guid(state_disk_image, u_boot_console):
Alison Chaiken1b11fb02017-09-09 23:47:13 -0700223 """Test the gpt guid command to save GUID into a string."""
224
225 if u_boot_console.config.buildconfig.get('config_cmd_gpt', 'n') != 'y':
226 pytest.skip('gpt command not supported')
Stephen Warren97dcbde2017-09-15 12:19:38 -0600227 u_boot_console.run_command('host bind 0 ' + state_disk_image.path)
Alison Chaiken1b11fb02017-09-09 23:47:13 -0700228 output = u_boot_console.run_command('gpt guid host 0 newguid')
229 output = u_boot_console.run_command('printenv newguid')
230 assert '375a56f7-d6c9-4e81-b5f0-09d41ca89efe' in output
Alison Chaikencb392962017-09-09 23:54:51 -0700231
Stephen Warren97dcbde2017-09-15 12:19:38 -0600232@pytest.mark.boardspec('sandbox')
Alison Chaikencb392962017-09-09 23:54:51 -0700233@pytest.mark.buildconfigspec('cmd_gpt')
Enric Balletbo i Serrabfd98c62023-01-10 17:19:35 +0100234@pytest.mark.requiredtool('sgdisk')
235def test_gpt_part_type_uuid(state_disk_image, u_boot_console):
236 """Test the gpt partittion type UUID command."""
237
238 u_boot_console.run_command('host bind 0 ' + state_disk_image.path)
239 output = u_boot_console.run_command('part type host 0:1')
240 assert '0fc63daf-8483-4772-8e79-3d69d8477de4' in output
241
242@pytest.mark.boardspec('sandbox')
243@pytest.mark.buildconfigspec('cmd_gpt')
244@pytest.mark.requiredtool('sgdisk')
245def test_gpt_part_type_save_uuid(state_disk_image, u_boot_console):
246 """Test the gpt partittion type to save UUID into a string."""
247
248 if u_boot_console.config.buildconfig.get('config_cmd_gpt', 'n') != 'y':
249 pytest.skip('gpt command not supported')
250 u_boot_console.run_command('host bind 0 ' + state_disk_image.path)
251 output = u_boot_console.run_command('part type host 0:1 newguid')
252 output = u_boot_console.run_command('printenv newguid')
253 assert '0fc63daf-8483-4772-8e79-3d69d8477de4' in output
254
255@pytest.mark.boardspec('sandbox')
256@pytest.mark.buildconfigspec('cmd_gpt')
Stephen Warren97dcbde2017-09-15 12:19:38 -0600257@pytest.mark.buildconfigspec('cmd_gpt_rename')
Patrick Delaunay0ffbb642017-10-18 15:11:07 +0200258@pytest.mark.buildconfigspec('cmd_part')
Stephen Warren2079db32017-09-18 11:11:49 -0600259@pytest.mark.requiredtool('sgdisk')
Stephen Warren97dcbde2017-09-15 12:19:38 -0600260def test_gpt_rename_partition(state_disk_image, u_boot_console):
Alison Chaikencb392962017-09-09 23:54:51 -0700261 """Test the gpt rename command to write partition names."""
262
Stephen Warren97dcbde2017-09-15 12:19:38 -0600263 u_boot_console.run_command('host bind 0 ' + state_disk_image.path)
Alison Chaikencb392962017-09-09 23:54:51 -0700264 u_boot_console.run_command('gpt rename host 0 1 first')
265 output = u_boot_console.run_command('gpt read host 0')
266 assert 'name first' in output
267 u_boot_console.run_command('gpt rename host 0 2 second')
268 output = u_boot_console.run_command('gpt read host 0')
269 assert 'name second' in output
Patrick Delaunay0ffbb642017-10-18 15:11:07 +0200270 output = u_boot_console.run_command('part list host 0')
Patrick Delaunayde7200a2017-12-06 18:08:20 +0100271 assert '0x00000800 0x00000fff "first"' in output
272 assert '0x00001000 0x00001bff "second"' in output
Alison Chaikencb392962017-09-09 23:54:51 -0700273
Stephen Warren97dcbde2017-09-15 12:19:38 -0600274@pytest.mark.boardspec('sandbox')
Alison Chaikencb392962017-09-09 23:54:51 -0700275@pytest.mark.buildconfigspec('cmd_gpt')
Stephen Warren97dcbde2017-09-15 12:19:38 -0600276@pytest.mark.buildconfigspec('cmd_gpt_rename')
277@pytest.mark.buildconfigspec('cmd_part')
Stephen Warren2079db32017-09-18 11:11:49 -0600278@pytest.mark.requiredtool('sgdisk')
Stephen Warren97dcbde2017-09-15 12:19:38 -0600279def test_gpt_swap_partitions(state_disk_image, u_boot_console):
Alison Chaikencb392962017-09-09 23:54:51 -0700280 """Test the gpt swap command to exchange two partition names."""
281
Stephen Warren97dcbde2017-09-15 12:19:38 -0600282 u_boot_console.run_command('host bind 0 ' + state_disk_image.path)
Alison Chaikencb392962017-09-09 23:54:51 -0700283 output = u_boot_console.run_command('part list host 0')
Joshua Wattd64d5792023-08-31 10:51:36 -0600284 assert '0x00000800 0x00000fff "part1"' in output
285 assert '0x00001000 0x00001bff "part2"' in output
286 u_boot_console.run_command('gpt swap host 0 part1 part2')
Alison Chaikencb392962017-09-09 23:54:51 -0700287 output = u_boot_console.run_command('part list host 0')
Joshua Wattd64d5792023-08-31 10:51:36 -0600288 assert '0x00000800 0x00000fff "part2"' in output
289 assert '0x00001000 0x00001bff "part1"' in output
Patrick Delaunay5751c052017-10-18 15:11:06 +0200290
Joshua Watt44d62332023-08-31 10:51:38 -0600291@pytest.mark.buildconfigspec('cmd_gpt')
292@pytest.mark.buildconfigspec('cmd_gpt_rename')
293@pytest.mark.buildconfigspec('cmd_part')
294@pytest.mark.requiredtool('sgdisk')
295def test_gpt_set_bootable(state_disk_image, u_boot_console):
296 """Test the gpt set-bootable command."""
297
298 u_boot_console.run_command('host bind 0 ' + state_disk_image.path)
299 parts = ('part2', 'part1')
300 for bootable in parts:
301 output = u_boot_console.run_command(f'gpt set-bootable host 0 {bootable}')
302 assert 'success!' in output
303
304 for p in parts:
305 output = u_boot_console.run_command(f'gpt setenv host 0 {p}')
306 assert 'success!' in output
307 output = u_boot_console.run_command('echo ${gpt_partition_bootable}')
308 if p == bootable:
309 assert output.rstrip() == '1'
310 else:
311 assert output.rstrip() == '0'
312
Patrick Delaunay5751c052017-10-18 15:11:06 +0200313@pytest.mark.boardspec('sandbox')
314@pytest.mark.buildconfigspec('cmd_gpt')
315@pytest.mark.buildconfigspec('cmd_part')
316@pytest.mark.requiredtool('sgdisk')
317def test_gpt_write(state_disk_image, u_boot_console):
318 """Test the gpt write command."""
319
320 u_boot_console.run_command('host bind 0 ' + state_disk_image.path)
321 output = u_boot_console.run_command('gpt write host 0 "name=all,size=0"')
322 assert 'Writing GPT: success!' in output
323 output = u_boot_console.run_command('part list host 0')
324 assert '0x00000022 0x00001fde "all"' in output
Patrick Delaunayde7200a2017-12-06 18:08:20 +0100325 output = u_boot_console.run_command('gpt write host 0 "uuid_disk=375a56f7-d6c9-4e81-b5f0-09d41ca89efe;name=first,start=1M,size=1M;name=second,start=0x200000,size=0x180000;"')
Patrick Delaunay5751c052017-10-18 15:11:06 +0200326 assert 'Writing GPT: success!' in output
327 output = u_boot_console.run_command('part list host 0')
Patrick Delaunayde7200a2017-12-06 18:08:20 +0100328 assert '0x00000800 0x00000fff "first"' in output
329 assert '0x00001000 0x00001bff "second"' in output
Patrick Delaunay5751c052017-10-18 15:11:06 +0200330 output = u_boot_console.run_command('gpt guid host 0')
331 assert '375a56f7-d6c9-4e81-b5f0-09d41ca89efe' in output
Joshua Wattd88ba5f2023-08-31 10:51:41 -0600332
333@pytest.mark.buildconfigspec('cmd_gpt')
334@pytest.mark.buildconfigspec('cmd_gpt_rename')
335@pytest.mark.buildconfigspec('cmd_part')
336@pytest.mark.requiredtool('sgdisk')
337def test_gpt_transpose(state_disk_image, u_boot_console):
338 """Test the gpt transpose command."""
339
340 u_boot_console.run_command('host bind 0 ' + state_disk_image.path)
341 output = u_boot_console.run_command('part list host 0')
342 assert '1\t0x00000800\t0x00000fff\t"part1"' in output
343 assert '2\t0x00001000\t0x00001bff\t"part2"' in output
344
345 output = u_boot_console.run_command('gpt transpose host 0 1 2')
346 assert 'success!' in output
347
348 output = u_boot_console.run_command('part list host 0')
349 assert '2\t0x00000800\t0x00000fff\t"part1"' in output
350 assert '1\t0x00001000\t0x00001bff\t"part2"' in output