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

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: Make SAFT work again. 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
27 def __getattr__(self, name): 132 def __getattr__(self, name):
28 ''' 133 '''
29 Retrieve a crosssystem attribute. 134 Retrieve a crosssystem attribute.
30 135
31 Attempt to access crossystemobject.name will invoke `crossystem name' 136 Attempt to access crossystemobject.name will invoke `crossystem name'
32 and return the stdout as the value. 137 and return the stdout as the value.
33 ''' 138 '''
34 return self.cros_if.run_shell_command_get_output( 139 return self.cros_if.run_shell_command_get_output(
35 'crossystem %s' % name)[0] 140 'crossystem %s' % name)[0]
36 141
37 def __setattr__(self, name, value): 142 def __setattr__(self, name, value):
38 if name in ('cros_if',): 143 if name in ('cros_if',):
39 self.__dict__[name] = value 144 self.__dict__[name] = value
40 else: 145 else:
41 self.cros_if.run_shell_command('crossystem "%s=%s"' % (name, value)) 146 self.cros_if.run_shell_command('crossystem "%s=%s"' % (name, value))
42 147
148 def request_recovery(self):
149 '''Request recovery mode next time the target reboots.'''
150
151 self.__setattr__('recovery_request', self.USER_RECOVERY_REQUEST_CODE)
43 152
44 def get_boot_vector_base(self): 153 def get_boot_vector_base(self):
45 ''' 154 '''Convert system state into a legacy boot vector base.
46 Convert system state into a legacy boot vector base.
47 155
48 The first three legacy boot vector digits are the boot vector base 156 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 157 matching the current crossystem output, and returns a list of three
50 the BIOS through ACPI, but that scheme has been superseded by the 158 digits in symbolic representation, which become the base of the 5
51 'crossystem' interface. 159 digit boot state vecotr.
52 160
53 The digits of the boot vector base have the following significance 161 Should it be impossible to interpret the state, the function returns
54
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 162 partially built list, which is an indication of a problem for the
Randall Spangler 2011/04/19 19:40:32 'a partially built list'
vb 2011/04/19 21:15:22 Done.
89 caller (list shorter than 3 elements). 163 caller (list shorter than 3 elements).
90 ''' 164 '''
91 165
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 = [] 166 boot_vector = []
119 167
120 for vector_map in vector_maps: 168 for vector_map in self.VECTOR_MAPS:
121 for (digit, values) in vector_map.iteritems(): 169 for (digit, values) in vector_map.iteritems():
122 for (name, value) in values.iteritems(): 170 for (name, value) in values.iteritems():
123 if self.__getattr__(name) != value: 171 if self.__getattr__(name) != value:
124 break 172 break
125 else: 173 else:
126 boot_vector.append(digit) 174 boot_vector.append(digit)
127 break 175 break
128 176
129 return boot_vector 177 return boot_vector
130 178
131 def dump(self): 179 def dump(self):
132 '''Dump all values as multiline text.''' 180 '''Dump all crossystem values as multiline text.'''
181
133 return '\n'.join(self.cros_if.run_shell_command_get_output( 182 return '\n'.join(self.cros_if.run_shell_command_get_output(
134 'crossystem')) 183 'crossystem'))
135 184
136 185
137 class ChromeOSInterface(object): 186 class ChromeOSInterface(object):
138 '''An object to encapsulate OS services functions.''' 187 '''An object to encapsulate OS services functions.'''
139 188
140 def __init__(self, silent): 189 def __init__(self, silent):
141 '''Object construction time initialization. 190 '''Object construction time initialization.
142 191
(...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after
376 def read_partition(self, partition, size): 425 def read_partition(self, partition, size):
377 '''Read the requested partition, up to size bytes.''' 426 '''Read the requested partition, up to size bytes.'''
378 tmp_file = self.state_dir_file('part.tmp') 427 tmp_file = self.state_dir_file('part.tmp')
379 self.run_shell_command('dd if=%s of=%s bs=1 count=%d' % ( 428 self.run_shell_command('dd if=%s of=%s bs=1 count=%d' % (
380 partition, tmp_file, size)) 429 partition, tmp_file, size))
381 fileh = open(tmp_file, 'r') 430 fileh = open(tmp_file, 'r')
382 data = fileh.read() 431 data = fileh.read()
383 fileh.close() 432 fileh.close()
384 os.remove(tmp_file) 433 os.remove(tmp_file)
385 return data 434 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