You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
181 lines
6.1 KiB
181 lines
6.1 KiB
# Lint as: python2, python3
|
|
# Copyright 2014 The Chromium OS Authors. All rights reserved.
|
|
# Use of this source code is governed by a BSD-style license that can be
|
|
# found in the LICENSE file.
|
|
|
|
import gzip, logging, os, re
|
|
from autotest_lib.client.bin import utils
|
|
from autotest_lib.client.common_lib import error
|
|
|
|
class KernelConfig():
|
|
"""
|
|
Parse the kernel config and enable us to query it.
|
|
Used to verify the kernel config (see kernel_ConfigVerify).
|
|
"""
|
|
|
|
def _passed(self, msg):
|
|
logging.info('ok: %s', msg)
|
|
|
|
def _failed(self, msg):
|
|
logging.error('FAIL: %s', msg)
|
|
self._failures.append(msg)
|
|
|
|
def failures(self):
|
|
"""Return the list of failures that occured during the test.
|
|
|
|
@return a list of string describing errors that occured since
|
|
initialization.
|
|
"""
|
|
return self._failures
|
|
|
|
def _fatal(self, msg):
|
|
logging.error('FATAL: %s', msg)
|
|
raise error.TestError(msg)
|
|
|
|
def get(self, key, default):
|
|
"""Get the value associated to key or default if it does not exist
|
|
|
|
@param key: key to look for.
|
|
@param default: value returned if key is not set in self._config
|
|
"""
|
|
return self._config.get(key, default)
|
|
|
|
def _config_required(self, name, wanted):
|
|
value = self._config.get(name, None)
|
|
if value in wanted:
|
|
self._passed('"%s" was "%s" in kernel config' % (name, value))
|
|
else:
|
|
states = []
|
|
for state in wanted:
|
|
if state == None:
|
|
states.append("unset")
|
|
else:
|
|
states.append(state)
|
|
self._failed('"%s" was "%s" (wanted one of "%s") in kernel config' %
|
|
(name, value, '|'.join(states)))
|
|
|
|
def has_value(self, name, value):
|
|
"""Determine if the name config item has a specific value.
|
|
|
|
@param name: name of config item to test
|
|
@param value: value expected for the given config name
|
|
"""
|
|
self._config_required('CONFIG_%s' % (name), value)
|
|
|
|
def has_builtin(self, name):
|
|
"""Check if the specific config item is built-in (present but not
|
|
built as a module).
|
|
|
|
@param name: name of config item to test
|
|
"""
|
|
wanted = ['y']
|
|
if name in self._missing_ok:
|
|
wanted.append(None)
|
|
self.has_value(name, wanted)
|
|
|
|
def has_module(self, name):
|
|
"""Check if the specific config item is a module (present but not
|
|
built-in).
|
|
|
|
@param name: name of config item to test
|
|
"""
|
|
wanted = ['m']
|
|
if name in self._missing_ok:
|
|
wanted.append(None)
|
|
self.has_value(name, wanted)
|
|
|
|
def is_enabled(self, name):
|
|
"""Check if the specific config item is present (either built-in or
|
|
a module).
|
|
|
|
@param name: name of config item to test
|
|
"""
|
|
wanted = ['y', 'm']
|
|
if name in self._missing_ok:
|
|
wanted.append(None)
|
|
self.has_value(name, wanted)
|
|
|
|
def is_missing(self, name):
|
|
"""Check if the specific config item is not present (neither built-in
|
|
nor a module).
|
|
|
|
@param name: name of config item to test
|
|
"""
|
|
self.has_value(name, [None])
|
|
|
|
def is_exclusive(self, exclusive):
|
|
"""Given a config item regex, make sure only the expected items
|
|
are present in the kernel configs.
|
|
|
|
@param exclusive: hash containing "missing", "builtin", "module",
|
|
"enabled" each to be checked with the corresponding
|
|
has_* function based on config items matching the
|
|
"regex" value.
|
|
"""
|
|
expected = set()
|
|
for name in exclusive['missing']:
|
|
self.is_missing(name)
|
|
for name in exclusive['builtin']:
|
|
self.has_builtin(name)
|
|
expected.add('CONFIG_%s' % (name))
|
|
for name in exclusive['module']:
|
|
self.has_module(name)
|
|
expected.add('CONFIG_%s' % (name))
|
|
for name in exclusive['enabled']:
|
|
self.is_enabled(name)
|
|
expected.add('CONFIG_%s' % (name))
|
|
|
|
# Now make sure nothing else with the specified regex exists.
|
|
regex = r'CONFIG_%s' % (exclusive['regex'])
|
|
for name in self._config:
|
|
if not re.match(regex, name):
|
|
continue
|
|
if not name in expected:
|
|
self._failed('"%s" found for "%s" when only "%s" allowed' %
|
|
(name, regex, "|".join(expected)))
|
|
|
|
def _read_config(self):
|
|
"""Open the kernel's build config file. Attempt to use the built-in
|
|
symbols from /proc first, then fall back to looking for a text file
|
|
in /boot.
|
|
|
|
@return readlines for fileobj
|
|
"""
|
|
filename = '/proc/config.gz'
|
|
if not os.path.exists(filename):
|
|
utils.system("modprobe configs", ignore_status=True)
|
|
if os.path.exists(filename):
|
|
with gzip.open(filename, "r") as rf:
|
|
return rf.readlines()
|
|
|
|
filename = '/boot/config-%s' % utils.system_output('uname -r')
|
|
if os.path.exists(filename):
|
|
logging.info('Falling back to reading %s', filename)
|
|
with open(filename, "r") as rf:
|
|
return rf.readlines()
|
|
|
|
self._fatal("Cannot locate suitable kernel config file")
|
|
|
|
def initialize(self, missing_ok=None):
|
|
"""Load the kernel configuration and parse it.
|
|
"""
|
|
file_lines = self._read_config()
|
|
# Import kernel config variables into a dictionary for each searching.
|
|
config = dict()
|
|
for item in file_lines:
|
|
item = item.strip()
|
|
if not '=' in item:
|
|
continue
|
|
key, value = item.split('=', 1)
|
|
config[key] = value
|
|
|
|
# Make sure we actually loaded something sensible.
|
|
if len(config) == 0:
|
|
self._fatal('No CONFIG variables found!')
|
|
|
|
self._config = config
|
|
self._failures = []
|
|
self._missing_ok = set()
|
|
if missing_ok:
|
|
self._missing_ok |= set(missing_ok)
|