brintos

brintos / linux-shallow public Read only

0
0
Text · 9.4 KiB · bb0e671 Raw
278 lines · python
1#!/usr/bin/python32# SPDX-License-Identifier: GPL-2.03import unittest4import os5import time6import glob7import fcntl8try:9    import ioctl_opt as ioctl10except ImportError:11    ioctl = None12    pass13from dbc import *14 15# Artificial delay between set commands16SET_DELAY = 0.517 18 19class invalid_param(ctypes.Structure):20    _fields_ = [21        ("data", ctypes.c_uint8),22    ]23 24 25def system_is_secured() -> bool:26    fused_part = glob.glob("/sys/bus/pci/drivers/ccp/**/fused_part")[0]27    if os.path.exists(fused_part):28        with open(fused_part, "r") as r:29            return int(r.read()) == 130    return True31 32 33class DynamicBoostControlTest(unittest.TestCase):34    def __init__(self, data) -> None:35        self.d = None36        self.signature = b"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"37        self.uid = b"1111111111111111"38        super().__init__(data)39 40    def setUp(self) -> None:41        self.d = open(DEVICE_NODE)42        return super().setUp()43 44    def tearDown(self) -> None:45        if self.d:46            self.d.close()47        return super().tearDown()48 49 50class TestUnsupportedSystem(DynamicBoostControlTest):51    def setUp(self) -> None:52        if os.path.exists(DEVICE_NODE):53            self.skipTest("system is supported")54        with self.assertRaises(FileNotFoundError) as error:55            super().setUp()56        self.assertEqual(error.exception.errno, 2)57 58    def test_unauthenticated_nonce(self) -> None:59        """fetch unauthenticated nonce"""60        with self.assertRaises(ValueError) as error:61            get_nonce(self.d, None)62 63 64class TestInvalidIoctls(DynamicBoostControlTest):65    def __init__(self, data) -> None:66        self.data = invalid_param()67        self.data.data = 168        super().__init__(data)69 70    def setUp(self) -> None:71        if not os.path.exists(DEVICE_NODE):72            self.skipTest("system is unsupported")73        if not ioctl:74            self.skipTest("unable to test IOCTLs without ioctl_opt")75 76        return super().setUp()77 78    def test_invalid_nonce_ioctl(self) -> None:79        """tries to call get_nonce ioctl with invalid data structures"""80 81        # 0x1 (get nonce), and invalid data82        INVALID1 = ioctl.IOWR(ord("D"), 0x01, invalid_param)83        with self.assertRaises(OSError) as error:84            fcntl.ioctl(self.d, INVALID1, self.data, True)85        self.assertEqual(error.exception.errno, 22)86 87    def test_invalid_setuid_ioctl(self) -> None:88        """tries to call set_uid ioctl with invalid data structures"""89 90        # 0x2 (set uid), and invalid data91        INVALID2 = ioctl.IOW(ord("D"), 0x02, invalid_param)92        with self.assertRaises(OSError) as error:93            fcntl.ioctl(self.d, INVALID2, self.data, True)94        self.assertEqual(error.exception.errno, 22)95 96    def test_invalid_setuid_rw_ioctl(self) -> None:97        """tries to call set_uid ioctl with invalid data structures"""98 99        # 0x2 as RW (set uid), and invalid data100        INVALID3 = ioctl.IOWR(ord("D"), 0x02, invalid_param)101        with self.assertRaises(OSError) as error:102            fcntl.ioctl(self.d, INVALID3, self.data, True)103        self.assertEqual(error.exception.errno, 22)104 105    def test_invalid_param_ioctl(self) -> None:106        """tries to call param ioctl with invalid data structures"""107        # 0x3 (param), and invalid data108        INVALID4 = ioctl.IOWR(ord("D"), 0x03, invalid_param)109        with self.assertRaises(OSError) as error:110            fcntl.ioctl(self.d, INVALID4, self.data, True)111        self.assertEqual(error.exception.errno, 22)112 113    def test_invalid_call_ioctl(self) -> None:114        """tries to call the DBC ioctl with invalid data structures"""115        # 0x4, and invalid data116        INVALID5 = ioctl.IOWR(ord("D"), 0x04, invalid_param)117        with self.assertRaises(OSError) as error:118            fcntl.ioctl(self.d, INVALID5, self.data, True)119        self.assertEqual(error.exception.errno, 22)120 121 122class TestInvalidSignature(DynamicBoostControlTest):123    def setUp(self) -> None:124        if not os.path.exists(DEVICE_NODE):125            self.skipTest("system is unsupported")126        if not system_is_secured():127            self.skipTest("system is unfused")128        return super().setUp()129 130    def test_unauthenticated_nonce(self) -> None:131        """fetch unauthenticated nonce"""132        get_nonce(self.d, None)133 134    def test_multiple_unauthenticated_nonce(self) -> None:135        """ensure state machine always returns nonce"""136        for count in range(0, 2):137            get_nonce(self.d, None)138 139    def test_authenticated_nonce(self) -> None:140        """fetch authenticated nonce"""141        get_nonce(self.d, None)142        with self.assertRaises(OSError) as error:143            get_nonce(self.d, self.signature)144        self.assertEqual(error.exception.errno, 22)145 146    def test_set_uid(self) -> None:147        """set uid"""148        get_nonce(self.d, None)149        with self.assertRaises(OSError) as error:150            set_uid(self.d, self.uid, self.signature)151        self.assertEqual(error.exception.errno, 1)152 153    def test_get_param(self) -> None:154        """fetch a parameter"""155        with self.assertRaises(OSError) as error:156            process_param(self.d, PARAM_GET_SOC_PWR_CUR, self.signature)157        self.assertEqual(error.exception.errno, 11)158 159    def test_set_param(self) -> None:160        """set a parameter"""161        with self.assertRaises(OSError) as error:162            process_param(self.d, PARAM_SET_PWR_CAP, self.signature, 1000)163        self.assertEqual(error.exception.errno, 11)164 165 166class TestUnFusedSystem(DynamicBoostControlTest):167    def setup_identity(self) -> None:168        """sets up the identity of the caller"""169        # if already authenticated these may fail170        try:171            get_nonce(self.d, None)172        except PermissionError:173            pass174        try:175            set_uid(self.d, self.uid, self.signature)176        except BlockingIOError:177            pass178        try:179            get_nonce(self.d, self.signature)180        except PermissionError:181            pass182 183    def setUp(self) -> None:184        if not os.path.exists(DEVICE_NODE):185            self.skipTest("system is unsupported")186        if system_is_secured():187            self.skipTest("system is fused")188        super().setUp()189        self.setup_identity()190        time.sleep(SET_DELAY)191 192    def test_get_valid_param(self) -> None:193        """fetch all possible parameters"""194        # SOC power195        soc_power_max = process_param(self.d, PARAM_GET_SOC_PWR_MAX, self.signature)196        soc_power_min = process_param(self.d, PARAM_GET_SOC_PWR_MIN, self.signature)197        self.assertGreater(soc_power_max[0], soc_power_min[0])198 199        # fmax200        fmax_max = process_param(self.d, PARAM_GET_FMAX_MAX, self.signature)201        fmax_min = process_param(self.d, PARAM_GET_FMAX_MIN, self.signature)202        self.assertGreater(fmax_max[0], fmax_min[0])203 204        # cap values205        keys = {206            "fmax-cap": PARAM_GET_FMAX_CAP,207            "power-cap": PARAM_GET_PWR_CAP,208            "current-temp": PARAM_GET_CURR_TEMP,209            "soc-power-cur": PARAM_GET_SOC_PWR_CUR,210        }211        for k in keys:212            result = process_param(self.d, keys[k], self.signature)213            self.assertGreater(result[0], 0)214 215    def test_get_invalid_param(self) -> None:216        """fetch an invalid parameter"""217        try:218            set_uid(self.d, self.uid, self.signature)219        except OSError:220            pass221        with self.assertRaises(OSError) as error:222            process_param(self.d, (0xF,), self.signature)223        self.assertEqual(error.exception.errno, 22)224 225    def test_set_fmax(self) -> None:226        """get/set fmax limit"""227        # fetch current228        original = process_param(self.d, PARAM_GET_FMAX_CAP, self.signature)229 230        # set the fmax231        target = original[0] - 100232        process_param(self.d, PARAM_SET_FMAX_CAP, self.signature, target)233        time.sleep(SET_DELAY)234        new = process_param(self.d, PARAM_GET_FMAX_CAP, self.signature)235        self.assertEqual(new[0], target)236 237        # revert back to current238        process_param(self.d, PARAM_SET_FMAX_CAP, self.signature, original[0])239        time.sleep(SET_DELAY)240        cur = process_param(self.d, PARAM_GET_FMAX_CAP, self.signature)241        self.assertEqual(cur[0], original[0])242 243    def test_set_power_cap(self) -> None:244        """get/set power cap limit"""245        # fetch current246        original = process_param(self.d, PARAM_GET_PWR_CAP, self.signature)247 248        # set the fmax249        target = original[0] - 10250        process_param(self.d, PARAM_SET_PWR_CAP, self.signature, target)251        time.sleep(SET_DELAY)252        new = process_param(self.d, PARAM_GET_PWR_CAP, self.signature)253        self.assertEqual(new[0], target)254 255        # revert back to current256        process_param(self.d, PARAM_SET_PWR_CAP, self.signature, original[0])257        time.sleep(SET_DELAY)258        cur = process_param(self.d, PARAM_GET_PWR_CAP, self.signature)259        self.assertEqual(cur[0], original[0])260 261    def test_set_3d_graphics_mode(self) -> None:262        """set/get 3d graphics mode"""263        # these aren't currently implemented but may be some day264        # they are *expected* to fail265        with self.assertRaises(OSError) as error:266            process_param(self.d, PARAM_GET_GFX_MODE, self.signature)267        self.assertEqual(error.exception.errno, 2)268 269        time.sleep(SET_DELAY)270 271        with self.assertRaises(OSError) as error:272            process_param(self.d, PARAM_SET_GFX_MODE, self.signature, 1)273        self.assertEqual(error.exception.errno, 2)274 275 276if __name__ == "__main__":277    unittest.main()278