xref: /aosp_15_r20/external/autotest/client/site_tests/hardware_SsdDetection/hardware_SsdDetection.py (revision 9c5db1993ded3edbeafc8092d69fe5de2ee02df7)
1# Lint as: python2, python3
2# Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
6import os
7import re
8
9from autotest_lib.client.bin import test, utils
10from autotest_lib.client.common_lib import error
11
12class hardware_SsdDetection(test.test):
13    """Verify that a flash device is present. """
14
15    version = 1
16    # Keep a list of boards that are expected to ship with hard drive.
17    boards_with_hdd = ['butterfly', 'kiev', 'parrot', 'stout']
18
19    def setup(self):
20        """
21        create a empty srcdir to prevent the error that checks
22        .version file
23        """
24        if not os.path.exists(self.srcdir):
25            utils.system('mkdir %s' % self.srcdir)
26
27
28    def run_once(self, check_link_speed=()):
29        """
30        Use rootdev to find the underlying block device even if the
31        system booted to /dev/dm-0.
32        """
33        device = utils.get_root_device()
34
35        def is_fixed(dev):
36            """ Check the device is fixed.
37
38            @param dev: device to check, i.e. 'sda'.
39            """
40            sysfs_path = '/sys/block/%s/removable' % dev
41            return (os.path.exists(sysfs_path) and
42                    open(sysfs_path).read().strip() == '0')
43
44        # Catch device name like sda, mmcblk0, nvme0n1.
45        device_re = re.compile(r'^/dev/([a-zA-Z0-9]+)$')
46        dev = device_re.findall(device)
47        if len(dev) != 1 or not is_fixed(dev[0]):
48            raise error.TestFail('The main disk %s is not fixed' % dev)
49
50        # If it is an mmcblk or nvme device, then it is SSD.
51        # Else run hdparm to check for SSD.
52        if re.search("nvme", device):
53            return
54
55        if re.search("mmcblk", device):
56            return
57
58        type_path = '/sys/block/%s/device/type' % dev[0]
59        type = os.path.realpath(type_path)
60        if re.search("ufs", type):
61            return
62
63        hdparm = utils.run('/sbin/hdparm -I %s' % device)
64
65        # Check if device is a SSD
66        match = re.search(r'Nominal Media Rotation Rate: (.+)$',
67                          hdparm.stdout, re.MULTILINE)
68        if match and match.group(1):
69            if match.group(1) != 'Solid State Device':
70                if utils.get_board() in self.boards_with_hdd:
71                    return
72                raise error.TestFail('The main disk is not a SSD, '
73                    'Rotation Rate: %s' % match.group(1))
74        else:
75            raise error.TestFail(
76                'Rotation Rate not reported from the device, '
77                'unable to ensure it is a SSD')
78
79        # Check if SSD is > 8GB in size
80        match = re.search("device size with M = 1000\*1000: (.+) MBytes",
81                          hdparm.stdout, re.MULTILINE)
82        if match and match.group(1):
83            size = int(match.group(1))
84            self.write_perf_keyval({"mb_ssd_device_size" : size})
85        else:
86            raise error.TestFail(
87                'Device size info missing from the device')
88
89        # Check supported link speed.
90        #
91        # check_link_speed is an empty tuple by default, which does not perform
92        # link speed checking.  You can run the test while specifying
93        # check_link_speed=('1.5Gb/s', '3.0Gb/s') to check the 2 signaling
94        # speeds are both supported.
95        for link_speed in check_link_speed:
96            if not re.search(r'Gen. signaling speed \(%s\)' % link_speed,
97                             hdparm.stdout, re.MULTILINE):
98                raise error.TestFail('Link speed %s not supported' % link_speed)
99