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