1# SPDX-License-Identifier: GPL-2.0
2# Copyright (c) 2017 Alison Chaiken
3# Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved.
4
5# Test GPT manipulation commands.
6
7import os
8import pytest
9import u_boot_utils
10
11"""
12These tests rely on a 4 MB disk image, which is automatically created by
13the test.
14"""
15
16# Mark all tests here as slow
17pytestmark = pytest.mark.slow
18
19class GptTestDiskImage(object):
20    """Disk Image used by the GPT tests."""
21
22    def __init__(self, u_boot_console):
23        """Initialize a new GptTestDiskImage object.
24
25        Args:
26            u_boot_console: A U-Boot console.
27
28        Returns:
29            Nothing.
30        """
31
32        filename = 'test_gpt_disk_image.bin'
33
34        persistent = u_boot_console.config.persistent_data_dir + '/' + filename
35        self.path = u_boot_console.config.result_dir  + '/' + filename
36
37        with u_boot_utils.persistent_file_helper(u_boot_console.log, persistent):
38            if os.path.exists(persistent):
39                u_boot_console.log.action('Disk image file ' + persistent +
40                    ' already exists')
41            else:
42                u_boot_console.log.action('Generating ' + persistent)
43                fd = os.open(persistent, os.O_RDWR | os.O_CREAT)
44                os.ftruncate(fd, 4194304)
45                os.close(fd)
46                cmd = ('sgdisk',
47                    '--disk-guid=375a56f7-d6c9-4e81-b5f0-09d41ca89efe',
48                    persistent)
49                u_boot_utils.run_and_log(u_boot_console, cmd)
50                # part1 offset 1MB size 1MB
51                cmd = ('sgdisk', '--new=1:2048:4095', '--change-name=1:part1',
52                    persistent)
53                # part2 offset 2MB size 1.5MB
54                u_boot_utils.run_and_log(u_boot_console, cmd)
55                cmd = ('sgdisk', '--new=2:4096:7167', '--change-name=2:part2',
56                    persistent)
57                u_boot_utils.run_and_log(u_boot_console, cmd)
58                cmd = ('sgdisk', '--load-backup=' + persistent)
59                u_boot_utils.run_and_log(u_boot_console, cmd)
60
61        cmd = ('cp', persistent, self.path)
62        u_boot_utils.run_and_log(u_boot_console, cmd)
63
64gtdi = None
65@pytest.fixture(scope='function')
66def state_disk_image(u_boot_console):
67    """pytest fixture to provide a GptTestDiskImage object to tests.
68    This is function-scoped because it uses u_boot_console, which is also
69    function-scoped. However, we don't need to actually do any function-scope
70    work, so this simply returns the same object over and over each time."""
71
72    global gtdi
73    if not gtdi:
74        gtdi = GptTestDiskImage(u_boot_console)
75    return gtdi
76
77@pytest.mark.boardspec('sandbox')
78@pytest.mark.buildconfigspec('cmd_gpt')
79@pytest.mark.buildconfigspec('cmd_part')
80@pytest.mark.requiredtool('sgdisk')
81def test_gpt_read(state_disk_image, u_boot_console):
82    """Test the gpt read command."""
83
84    u_boot_console.run_command('host bind 0 ' + state_disk_image.path)
85    output = u_boot_console.run_command('gpt read host 0')
86    assert 'Start 1MiB, size 1MiB' in output
87    assert 'Block size 512, name part1' in output
88    assert 'Start 2MiB, size 1MiB' in output
89    assert 'Block size 512, name part2' in output
90    output = u_boot_console.run_command('part list host 0')
91    assert '0x00000800	0x00000fff	"part1"' in output
92    assert '0x00001000	0x00001bff	"part2"' in output
93
94@pytest.mark.boardspec('sandbox')
95@pytest.mark.buildconfigspec('cmd_gpt')
96@pytest.mark.requiredtool('sgdisk')
97def test_gpt_verify(state_disk_image, u_boot_console):
98    """Test the gpt verify command."""
99
100    u_boot_console.run_command('host bind 0 ' + state_disk_image.path)
101    output = u_boot_console.run_command('gpt verify host 0')
102    assert 'Verify GPT: success!' in output
103
104@pytest.mark.boardspec('sandbox')
105@pytest.mark.buildconfigspec('cmd_gpt')
106@pytest.mark.requiredtool('sgdisk')
107def test_gpt_repair(state_disk_image, u_boot_console):
108    """Test the gpt repair command."""
109
110    u_boot_console.run_command('host bind 0 ' + state_disk_image.path)
111    output = u_boot_console.run_command('gpt repair host 0')
112    assert 'Repairing GPT: success!' in output
113
114@pytest.mark.boardspec('sandbox')
115@pytest.mark.buildconfigspec('cmd_gpt')
116@pytest.mark.requiredtool('sgdisk')
117def test_gpt_guid(state_disk_image, u_boot_console):
118    """Test the gpt guid command."""
119
120    u_boot_console.run_command('host bind 0 ' + state_disk_image.path)
121    output = u_boot_console.run_command('gpt guid host 0')
122    assert '375a56f7-d6c9-4e81-b5f0-09d41ca89efe' in output
123
124@pytest.mark.boardspec('sandbox')
125@pytest.mark.buildconfigspec('cmd_gpt')
126@pytest.mark.requiredtool('sgdisk')
127def test_gpt_save_guid(state_disk_image, u_boot_console):
128    """Test the gpt guid command to save GUID into a string."""
129
130    if u_boot_console.config.buildconfig.get('config_cmd_gpt', 'n') != 'y':
131        pytest.skip('gpt command not supported')
132    u_boot_console.run_command('host bind 0 ' + state_disk_image.path)
133    output = u_boot_console.run_command('gpt guid host 0 newguid')
134    output = u_boot_console.run_command('printenv newguid')
135    assert '375a56f7-d6c9-4e81-b5f0-09d41ca89efe' in output
136
137@pytest.mark.boardspec('sandbox')
138@pytest.mark.buildconfigspec('cmd_gpt')
139@pytest.mark.requiredtool('sgdisk')
140def test_gpt_part_type_uuid(state_disk_image, u_boot_console):
141    """Test the gpt partittion type UUID command."""
142
143    u_boot_console.run_command('host bind 0 ' + state_disk_image.path)
144    output = u_boot_console.run_command('part type host 0:1')
145    assert '0fc63daf-8483-4772-8e79-3d69d8477de4' in output
146
147@pytest.mark.boardspec('sandbox')
148@pytest.mark.buildconfigspec('cmd_gpt')
149@pytest.mark.requiredtool('sgdisk')
150def test_gpt_part_type_save_uuid(state_disk_image, u_boot_console):
151    """Test the gpt partittion type to save UUID into a string."""
152
153    if u_boot_console.config.buildconfig.get('config_cmd_gpt', 'n') != 'y':
154        pytest.skip('gpt command not supported')
155    u_boot_console.run_command('host bind 0 ' + state_disk_image.path)
156    output = u_boot_console.run_command('part type host 0:1 newguid')
157    output = u_boot_console.run_command('printenv newguid')
158    assert '0fc63daf-8483-4772-8e79-3d69d8477de4' in output
159
160@pytest.mark.boardspec('sandbox')
161@pytest.mark.buildconfigspec('cmd_gpt')
162@pytest.mark.buildconfigspec('cmd_gpt_rename')
163@pytest.mark.buildconfigspec('cmd_part')
164@pytest.mark.requiredtool('sgdisk')
165def test_gpt_rename_partition(state_disk_image, u_boot_console):
166    """Test the gpt rename command to write partition names."""
167
168    u_boot_console.run_command('host bind 0 ' + state_disk_image.path)
169    u_boot_console.run_command('gpt rename host 0 1 first')
170    output = u_boot_console.run_command('gpt read host 0')
171    assert 'name first' in output
172    u_boot_console.run_command('gpt rename host 0 2 second')
173    output = u_boot_console.run_command('gpt read host 0')
174    assert 'name second' in output
175    output = u_boot_console.run_command('part list host 0')
176    assert '0x00000800	0x00000fff	"first"' in output
177    assert '0x00001000	0x00001bff	"second"' in output
178
179@pytest.mark.boardspec('sandbox')
180@pytest.mark.buildconfigspec('cmd_gpt')
181@pytest.mark.buildconfigspec('cmd_gpt_rename')
182@pytest.mark.buildconfigspec('cmd_part')
183@pytest.mark.requiredtool('sgdisk')
184def test_gpt_swap_partitions(state_disk_image, u_boot_console):
185    """Test the gpt swap command to exchange two partition names."""
186
187    u_boot_console.run_command('host bind 0 ' + state_disk_image.path)
188    output = u_boot_console.run_command('part list host 0')
189    assert '0x00000800	0x00000fff	"first"' in output
190    assert '0x00001000	0x00001bff	"second"' in output
191    u_boot_console.run_command('gpt swap host 0 first second')
192    output = u_boot_console.run_command('part list host 0')
193    assert '0x00000800	0x00000fff	"second"' in output
194    assert '0x00001000	0x00001bff	"first"' in output
195
196@pytest.mark.boardspec('sandbox')
197@pytest.mark.buildconfigspec('cmd_gpt')
198@pytest.mark.buildconfigspec('cmd_part')
199@pytest.mark.requiredtool('sgdisk')
200def test_gpt_write(state_disk_image, u_boot_console):
201    """Test the gpt write command."""
202
203    u_boot_console.run_command('host bind 0 ' + state_disk_image.path)
204    output = u_boot_console.run_command('gpt write host 0 "name=all,size=0"')
205    assert 'Writing GPT: success!' in output
206    output = u_boot_console.run_command('part list host 0')
207    assert '0x00000022	0x00001fde	"all"' in output
208    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;"')
209    assert 'Writing GPT: success!' in output
210    output = u_boot_console.run_command('part list host 0')
211    assert '0x00000800	0x00000fff	"first"' in output
212    assert '0x00001000	0x00001bff	"second"' in output
213    output = u_boot_console.run_command('gpt guid host 0')
214    assert '375a56f7-d6c9-4e81-b5f0-09d41ca89efe' in output
215