Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(623)

Side by Side Diff: chromeos_interface.py

Issue 6881019: Fix SAFT to work on all x86 platforms using crossystem. (Closed) Base URL: ssh://gitrw.chromium.org:9222/saft.git@master
Patch Set: Fix another Mario recovery reason shortcoming. Created 9 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | saft_utility.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 #!/usr/bin/python 1 #!/usr/bin/python
2 # Copyright (c) 2010 The Chromium OS Authors. All rights reserved. 2 # Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be 3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file. 4 # found in the LICENSE file.
5 5
6 '''A module to provide interface to ChromeOS services.''' 6 '''A module to provide interface to ChromeOS services.'''
7 7
8 import datetime 8 import datetime
9 import os 9 import os
10 import re 10 import re
11 import shutil 11 import shutil
12 import struct 12 import struct
13 import subprocess 13 import subprocess
14 import tempfile 14 import tempfile
15 import time 15 import time
16 16
17 class ChromeOSInterfaceError(Exception): 17 class ChromeOSInterfaceError(Exception):
18 '''ChromeOS interface specific exception.''' 18 '''ChromeOS interface specific exception.'''
19 pass 19 pass
20 20
21 class Crossystem(object): 21 class Crossystem(object):
22 '''A wrapper for the crossystem utility.''' 22 '''A wrapper for the crossystem utility.'''
23 23
24 # Code dedicated for user triggering recovery mode through crossystem.
25 USER_RECOVERY_REQUEST_CODE = '193'
26
27 '''
28 The first three legacy boot vector digits are the boot vector base (the
29 entire vector consists of 5 digits). They used to be reported by the BIOS
30 through ACPI, but that scheme has been superseded by the 'crossystem'
31 interface.
32
33 The digits of the boot vector base have the following significance
34
35 - first digit -
36 1 - normal boot
37 2 - developer mode boot
38 3 - recovery initialed by pressing the recovery button
39 4 - recovery from developer mode warning screen
40 5 - recovery caused by both firmware images being invalid
41 6 - recovery caused by both kernel images being invalid
42 8 - recovery initiated by user
43
44 - second digit -
45 0 - recovery firmware
46 1 - rewritable firmware A
47 2 - rewritable firmware B
48
49 - third digit -
50 0 - Read only (recovery) EC firmware
51 1 - rewritable EC firmware
52
53
54 Below is a list of dictionaries to map current system state as reported by
55 'crossystem' into the 'legacy' boot vector digits.
56
57 The three elements of the list represent the three digits of the boot
58 vector. Each list element is a dictionary where the key is the legacy boot
59 vector value in the appropriate position, and the value is in turn a
60 dictionary of name-value pairs.
61
62 If all name-value pairs of a dictionary element match those reported by
63 crossystem, the legacy representation number is considered the appropriate
64 vector digit.
65
66 Note that on some platforms (namely, Mario) same parameters returned by
67 crossystem are set to a wrong value. The class init() routine adjust the
68 list to support those platforms.
69 '''
70
71 VECTOR_MAPS = [
72 { # first vector position
73 '1': {
74 'devsw_boot': '0',
75 'mainfw_type': 'normal',
76 'recoverysw_boot': '0',
77 },
78 '5': {
79 'devsw_boot': '0',
80 'recoverysw_boot': '0',
81 'recovery_reason' : '3',
82 'mainfw_type': 'recovery',
83 },
84 '6': {
85 'devsw_boot': '0',
86 'recoverysw_boot': '0',
87 'recovery_reason' : '66',
88 'mainfw_type': 'recovery',
89 },
90 '8': {
91 'devsw_boot': '0',
92 'recoverysw_boot': '0',
93 'recovery_reason' : USER_RECOVERY_REQUEST_CODE,
94 'mainfw_type': 'recovery',
95 },
96 },
97 { # second vector position
98 '0': {'mainfw_type': 'recovery',},
99 '1': {
100 'mainfw_type': 'normal',
101 'mainfw_act': 'A'
102 },
103 '2': {
104 'mainfw_type': 'normal',
105 'mainfw_act': 'B'
106 },
107 },
108 { # third vector position
109 '0': {'ecfw_act': 'RO',},
110 '1': {'ecfw_act': 'RW',},
111 },
112 ]
113
24 def init(self, cros_if): 114 def init(self, cros_if):
115 '''Init the instance. If running on Mario - adjust the map.'''
116
25 self.cros_if = cros_if 117 self.cros_if = cros_if
26 118
119 # Hack Alert!!! Adjust vector map to work on Mario
120 fwid = self.__getattr__('fwid').lower()
121 if not 'mario' in fwid:
122 return
123 # Mario firmware is broken and always reports recovery switch as set
124 # at boot time when booting up in recovery mode. This is why we
125 # exclude recoverysw_boot from the map when running on mario.
126 for state in self.VECTOR_MAPS[0].itervalues():
127 if state['mainfw_type'] != 'recovery':
128 continue
129 if 'recoverysw_boot' in state:
130 del(state['recoverysw_boot'])
131 if state['recovery_reason'] == self.USER_RECOVERY_REQUEST_CODE:
132 # This is the only recovery reason Mario knows about
133 state['recovery_reason'] = '1'
134
27 def __getattr__(self, name): 135 def __getattr__(self, name):
28 ''' 136 '''
29 Retrieve a crosssystem attribute. 137 Retrieve a crosssystem attribute.
30 138
31 Attempt to access crossystemobject.name will invoke `crossystem name' 139 Attempt to access crossystemobject.name will invoke `crossystem name'
32 and return the stdout as the value. 140 and return the stdout as the value.
33 ''' 141 '''
34 return self.cros_if.run_shell_command_get_output( 142 return self.cros_if.run_shell_command_get_output(
35 'crossystem %s' % name)[0] 143 'crossystem %s' % name)[0]
36 144
37 def __setattr__(self, name, value): 145 def __setattr__(self, name, value):
38 if name in ('cros_if',): 146 if name in ('cros_if',):
39 self.__dict__[name] = value 147 self.__dict__[name] = value
40 else: 148 else:
41 self.cros_if.run_shell_command('crossystem "%s=%s"' % (name, value)) 149 self.cros_if.run_shell_command('crossystem "%s=%s"' % (name, value))
42 150
151 def request_recovery(self):
152 '''Request recovery mode next time the target reboots.'''
153
154 self.__setattr__('recovery_request', self.USER_RECOVERY_REQUEST_CODE)
43 155
44 def get_boot_vector_base(self): 156 def get_boot_vector_base(self):
45 ''' 157 '''Convert system state into a legacy boot vector base.
46 Convert system state into a legacy boot vector base.
47 158
48 The first three legacy boot vector digits are the boot vector base 159 The function looks up the VECTOR_MAPS list above to find the digits
49 (the entire vector consists of 5 digits). They used to be reported by 160 matching the current crossystem output, and returns a list of three
50 the BIOS through ACPI, but that scheme has been superseded by the 161 digits in symbolic representation, which become the base of the 5
51 'crossystem' interface. 162 digit boot state vector.
52 163
53 The digits of the boot vector base have the following significance 164 Should it be impossible to interpret the state, the function returns
54 165 a partially built list, which is an indication of a problem for the
55 - first digit -
56 1 - normal boot
57 2 - developer mode boot
58 3 - recovery initialed by pressing the recovery button
59 4 - recovery from developer mode warning screen
60 5 - recovery caused by both firmware images being invalid
61 6 - recovery caused by both kernel images being invalid
62
63 - second digit -
64 0 - recovery firmware
65 1 - rewritable firmware A
66 2 - rewritable firmware B
67
68 - third digit -
69 0 - Read only (recovery) EC firmware
70 1 - rewritable EC firmware
71
72
73 This function uses a three tuple of dictionaries to map current system
74 state as reported by 'crossystem' into the 'legacy' boot vector
75 digits.
76
77 Each tuple element is a dictionary, where the key is the 'legacy'
78 representation of the state, and the value is a yet another dictionary
79 of name-value pairs.
80
81 If all name-value pairs match those in the crossystem output, the
82 legacy representation number is returned as the appropriate vector
83 number.
84
85 The function returns a list of three digits in symbolic representation.
86
87 Should it be impossible to interpret the state, the function returns a
88 partially built list, which is an indication of a problem for the
89 caller (list shorter than 3 elements). 166 caller (list shorter than 3 elements).
90 ''' 167 '''
91 168
92 vector_maps = (
93 { # first vector position
94 '1': {
95 'devsw_boot': '0',
96 'recoverysw_boot': '0',
97 'recovery_reason' : '0',
98 'tried_fwb' : '0',
99 },
100 },
101 { # second vector position
102 '0': {'mainfw_type': 'recovery',},
103 '1': {
104 'mainfw_type': 'normal',
105 'mainfw_act': 'A'
106 },
107 '2': {
108 'mainfw_type': 'normal',
109 'mainfw_act': 'B'
110 },
111 },
112 { # third vector position
113 '0': {'ecfw_act': 'RO',},
114 '1': {'ecfw_act': 'RW',},
115 },
116 )
117
118 boot_vector = [] 169 boot_vector = []
119 170
120 for vector_map in vector_maps: 171 for vector_map in self.VECTOR_MAPS:
121 for (digit, values) in vector_map.iteritems(): 172 for (digit, values) in vector_map.iteritems():
122 for (name, value) in values.iteritems(): 173 for (name, value) in values.iteritems():
123 if self.__getattr__(name) != value: 174 if self.__getattr__(name) != value:
124 break 175 break
125 else: 176 else:
126 boot_vector.append(digit) 177 boot_vector.append(digit)
127 break 178 break
128 179
129 return boot_vector 180 return boot_vector
130 181
131 def dump(self): 182 def dump(self):
132 '''Dump all values as multiline text.''' 183 '''Dump all crossystem values as multiline text.'''
184
133 return '\n'.join(self.cros_if.run_shell_command_get_output( 185 return '\n'.join(self.cros_if.run_shell_command_get_output(
134 'crossystem')) 186 'crossystem'))
135 187
136 188
137 class ChromeOSInterface(object): 189 class ChromeOSInterface(object):
138 '''An object to encapsulate OS services functions.''' 190 '''An object to encapsulate OS services functions.'''
139 191
140 def __init__(self, silent): 192 def __init__(self, silent):
141 '''Object construction time initialization. 193 '''Object construction time initialization.
142 194
(...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after
376 def read_partition(self, partition, size): 428 def read_partition(self, partition, size):
377 '''Read the requested partition, up to size bytes.''' 429 '''Read the requested partition, up to size bytes.'''
378 tmp_file = self.state_dir_file('part.tmp') 430 tmp_file = self.state_dir_file('part.tmp')
379 self.run_shell_command('dd if=%s of=%s bs=1 count=%d' % ( 431 self.run_shell_command('dd if=%s of=%s bs=1 count=%d' % (
380 partition, tmp_file, size)) 432 partition, tmp_file, size))
381 fileh = open(tmp_file, 'r') 433 fileh = open(tmp_file, 'r')
382 data = fileh.read() 434 data = fileh.read()
383 fileh.close() 435 fileh.close()
384 os.remove(tmp_file) 436 os.remove(tmp_file)
385 return data 437 return data
OLDNEW
« no previous file with comments | « no previous file | saft_utility.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698