Home | History | Annotate | Download | only in kernel_BootMessagesServer
      1 # Copyright (c) 2011 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 
      5 import logging, os, re
      6 
      7 from autotest_lib.client.bin import utils
      8 from autotest_lib.client.common_lib import error
      9 from autotest_lib.server import test
     10 
     11 _KERN_WARNING = 4
     12 
     13 _WHITELIST_COMMON = [
     14     r"used greatest stack depth: \d+ bytes left",
     15     "Kernel-defined memdesc doesn't match the one from EFI!",
     16     "Use a HIGHMEM enabled kernel.",
     17    "GPT: Use GNU Parted to correct GPT errors.",
     18     r"GPT:\d+ != \d+",
     19     "GPT:Alternate GPT header not at the end of the disk.",
     20     "GPT:Primary header thinks Alt. header is not at the end of the disk.",
     21     r"GPT:partition_entry_array_crc32 values don't match: 0x[\da-f]+ !="
     22     " 0x[\da-f]+",
     23     r"Warning only \d+MB will be used.",
     24     "\[drm:intel_init_bios\] \*ERROR\* VBT signature missing",
     25     "i2c i2c-2: The new_device interface is still experimental and may change "
     26     "in a near future",
     27     "i915 0000:00:02.0: Invalid ROM contents",
     28     "industrialio: module is from the staging directory, the quality is "
     29     "unknown, you have been warned.",
     30     "pnp 00:01: io resource \(0x164e-0x164f\) overlaps 0000:00:1c.0 "
     31     "BAR 7 \(0x1000-0x1fff\), disabling",
     32     r"sd \d:\d:\d:\d: \[sd[a-z]\] Assuming drive cache: write through",
     33     "tsl[\da-z]+: module is from the staging directory, the quality is "
     34     "unknown, you have been warned.",
     35     "usb 1-2: unknown number of interfaces: 4",
     36 ]
     37 
     38 _WHITELIST_TARGETS = {
     39     'Alex' : [
     40         r"CE: hpet increasing min_delta_ns to \d+ nsec",
     41         r"Measured \d+ cycles TSC warp between CPUs, turning off TSC clock.",
     42         "pci 0000:01:00.0: BAR 6: no parent found for of device "
     43         "\[0xffff0000-0xffffffff]",
     44         "tsl258x 2-0029: taos_get_lux data not valid",
     45         "usb 1-2: config 1 has an invalid interface number: 1 but max is 0",
     46         "usb 1-2: config 1 has no interface number 0",
     47         ],
     48     'Mario' : [
     49         "chromeos_acpi: failed to retrieve MLST \(5\)",
     50         r"btusb_[a-z]{4}_complete: hci\d urb [\da-f]+ failed to resubmit \(1\)",
     51         ]
     52 }
     53 
     54 """ Interesting fields from meminfo that we want to log
     55     If you add fields here, you must add them to the constraints
     56     in the control file
     57 """
     58 _meminfo_fields = { 'MemFree'   : 'coldboot_memfree_mb',
     59                     'AnonPages' : 'coldboot_anonpages_mb',
     60                     'Buffers'   : 'coldboot_buffers_mb',
     61                     'Cached'    : 'coldboot_cached_mb',
     62                     'Active'    : 'coldboot_active_mb',
     63                     'Inactive'  : 'coldboot_inactive_mb',
     64                     }
     65 
     66 class kernel_BootMessagesServer(test.test):
     67     version = 1
     68 
     69 
     70     def _read_dmesg(self, filename):
     71         """Put the contents of 'dmesg -r' into the given file.
     72 
     73         @param filename: The file to write 'dmesg -r' into.
     74         """
     75         f = open(filename, 'w')
     76         self._client.run('dmesg -r', stdout_tee=f)
     77         f.close()
     78 
     79         return utils.read_file(filename)
     80 
     81     def _reboot_machine(self):
     82         """Reboot the client machine.
     83 
     84         We'll wait until the client is down, then up again.
     85         """
     86         self._client.run('reboot')
     87         self._client.wait_down()
     88         self._client.wait_up()
     89 
     90     def _read_meminfo(self, filename):
     91         """Fetch /proc/meminfo from client and return lines in the file
     92 
     93         @param filename: The file to write 'cat /proc/meminfo' into.
     94         """
     95 
     96         f = open(filename, 'w')
     97         self._client.run('cat /proc/meminfo', stdout_tee=f)
     98         f.close()
     99 
    100         return utils.read_file(filename)
    101 
    102     def _parse_meminfo(self, meminfo, perf_vals):
    103         """ Parse the contents of each line of meminfo
    104             if the line matches one of the interesting keys
    105             save it into perf_vals in terms of megabytes
    106 
    107             @param filelines: list of lines in meminfo
    108             @param perf_vals: dictionary of performance metrics
    109         """
    110 
    111         for line in meminfo.splitlines():
    112             stuff = re.match('(.*):\s+(\d+)', line)
    113             stat  = stuff.group(1)
    114             if stat in _meminfo_fields:
    115                 value  = int(stuff.group(2))/ 1024
    116                 metric = _meminfo_fields[stat]
    117                 perf_vals[metric] = value
    118 
    119     def _check_acpi_output(self, text, fwid):
    120         # This dictionary is the database of expected strings in dmesg output.
    121         # The keys are platform names, the values are two tuples, the first
    122         # element is the regex to filter the messages, the second element is a
    123         # set of strings to be found in the filtered dmesg set.
    124         message_db = {
    125             'Alex' : (r'(chromeos_acpi:|ChromeOS )', (
    126                     'chromeos_acpi: registering CHSW 0',
    127                     'chromeos_acpi: registering VBNV 0',
    128                     'chromeos_acpi: registering VBNV 1',
    129                     r'chromeos_acpi: truncating buffer from \d+ to \d+',
    130                     'chromeos_acpi: installed',
    131                     'ChromeOS firmware detected')),
    132 
    133             'Mario' : (r'(chromeos_acpi|ChromeOS )', (
    134                     'chromeos_acpi: falling back to default list of methods',
    135                     'chromeos_acpi: registering CHSW 0',
    136                     'chromeos_acpi: registering CHNV 0',
    137                     'chromeos_acpi: failed to retrieve MLST \(5\)',
    138                     'chromeos_acpi: installed',
    139                     'Legacy ChromeOS firmware detected'))
    140             }
    141 
    142         if fwid not in message_db:
    143             msg = 'Unnown platform %s, acpi dmesg set not defined.' % fwid
    144             logging.error(msg)
    145             raise error.TestFail(msg)
    146 
    147         rv = utils.verify_mesg_set(text,
    148                                    message_db[fwid][0],
    149                                    message_db[fwid][1])
    150         if rv:
    151             logging.error('ACPI mismatch\n%s:' % rv)
    152             raise error.TestFail('ACPI dmesg mismatch')
    153 
    154     def run_once(self, host=None):
    155         """Run the test.
    156 
    157         @param host: The client machine to connect to; should be a Host object.
    158         """
    159         assert host is not None, "The host must be specified."
    160 
    161         self._client = host
    162 
    163         # get the firmware identifier from Crossystem
    164         cs = utils.Crossystem(self._client)
    165         cs.init()
    166         fwid = cs.fwid().split('.')[0]
    167 
    168         dmesg_filename = os.path.join(self.resultsdir, 'dmesg')
    169         meminfo_filename = os.path.join(self.resultsdir, 'meminfo')
    170         perf_vals = {}
    171 
    172         self._reboot_machine()
    173         meminfo = self._read_meminfo(meminfo_filename)
    174         self._parse_meminfo(meminfo, perf_vals)
    175         dmesg = self._read_dmesg(dmesg_filename)
    176 
    177         if fwid not in _WHITELIST_TARGETS:
    178             msg = 'Unnown platform %s, whitelist dmesg set not defined.' % fwid
    179             logging.error(msg)
    180             raise error.TestFail(msg)
    181 
    182         unexpected = utils.check_raw_dmesg(
    183             dmesg, _KERN_WARNING, _WHITELIST_COMMON + _WHITELIST_TARGETS[fwid])
    184 
    185         if unexpected:
    186             f = open(os.path.join(self.resultsdir, 'dmesg.err'), 'w')
    187             for line in unexpected:
    188                 logging.error('UNEXPECTED DMESG: %s' % line)
    189                 f.write('%s\n' % line)
    190             f.close()
    191             raise error.TestFail("Unexpected dmesg warnings and/or errors.")
    192 
    193         self.write_perf_keyval(perf_vals)
    194 
    195         self._check_acpi_output(dmesg, fwid)
    196