1# Copyright (c) 2015 The Chromium OS Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5import logging
6import os
7
8from autotest_lib.client.bin import test, utils
9from autotest_lib.client.common_lib import error
10from autotest_lib.client.cros import kernel_config
11
12
13class kernel_FirmwareRequest(test.test):
14    """
15    Test asynchronous firmware loading
16    """
17    version = 1
18
19    def set_module_locking(self, enabled):
20        """
21        Enable/disable LSM request_firmware location locking
22        Inspired by security_ModuleLocking
23        """
24        sysctl = "/proc/sys/kernel/chromiumos/module_locking"
25        value = '1\n' if enabled else '0\n'
26
27        if os.path.exists(sysctl):
28            open(sysctl, "w").write(value)
29        else:
30            raise error.TestNAError("module locking sysctl not available; may not be able to load test FW")
31
32
33    def test_is_valid(self):
34        """
35        Check if this test is worth running, based on whether the kernel
36        .config has the right features
37        """
38        config = kernel_config.KernelConfig()
39        config.initialize()
40        config.is_enabled('TEST_FIRMWARE')
41        return len(config.failures()) == 0
42
43
44    def do_fw_test(self):
45        """
46        Run one iteration of the test
47        Return non-zero if failed
48        """
49        os.chdir(self.srcdir)
50        ret = utils.system("./fw_filesystem.sh", ignore_status=True)
51        if ret:
52            raise error.TestFail("FW request test failed: %d" % (ret))
53
54
55    def run_once(self):
56        """
57        This test will run the firmware request kernel self test (from
58        upstream). This tests that the request_firmware() and
59        request_firmware_nowait() kernel APIs are somewhat sane. It tries to
60        load the empty filename ("") as well as a small toy firmware, and
61        checks that it matches. It also makes sure a non-existent firmware
62        cannot be found.
63
64        We rerun the same test several times to increase the probability of
65        catching errors.
66
67        Needs to disable module locking so we can load test firmwares from
68        non-standard locations (e.g., /tmp)
69        """
70
71        num_loops = 50
72        module_name = "test_firmware"
73
74        if not self.test_is_valid():
75            raise error.TestNAError("FW test module is not available for this test")
76
77        utils.load_module(module_name)
78        if not utils.module_is_loaded(module_name):
79            raise error.TestNAError("FW test module is not available for this test")
80
81        try:
82            self.set_module_locking(False)
83
84            logging.info("iterations: %d", num_loops)
85
86            for i in range(0, num_loops):
87                self.do_fw_test()
88
89        finally:
90            self.set_module_locking(True)
91            utils.unload_module(module_name)
92