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