diff options
author | Mary Ruthven <mruthven@google.com> | 2018-04-17 16:55:32 -0700 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2018-04-19 03:37:14 -0700 |
commit | d9386134c156775a3c0b0c6d4638643a4f190aa3 (patch) | |
tree | ec64a61b69a2e26c5e2ffe15eaaec84cb36e6b54 /extra/cr50_rma_open/cr50_rma_open.py | |
parent | c6ce2208e3b6bf2fd1b51269dfdff4c57139af84 (diff) | |
download | chrome-ec-d9386134c156775a3c0b0c6d4638643a4f190aa3.tar.gz |
cr50_rma_open: check write protect too
Cr50 RMA Open will disable write protect. Make sure it is disabled. If
it isn't, manually disable write protect after rma_auth. If cr50 reboots
or loses write protect, cr50_rma_open can now be used to force disable
it again with cr50_rma_open -w.
BUG=none
BRANCH=none
TEST=none
Change-Id: I096cff51ae20b8a4cfbfa92892a011ff48f4cc49
Signed-off-by: Mary Ruthven <mruthven@google.com>
Reviewed-on: https://chromium-review.googlesource.com/1016023
Commit-Ready: Mary Ruthven <mruthven@chromium.org>
Tested-by: Mary Ruthven <mruthven@chromium.org>
Reviewed-by: Wai-Hong Tam <waihong@google.com>
Diffstat (limited to 'extra/cr50_rma_open/cr50_rma_open.py')
-rw-r--r-- | extra/cr50_rma_open/cr50_rma_open.py | 136 |
1 files changed, 100 insertions, 36 deletions
diff --git a/extra/cr50_rma_open/cr50_rma_open.py b/extra/cr50_rma_open/cr50_rma_open.py index 81ba82f5b5..28dbde711e 100644 --- a/extra/cr50_rma_open/cr50_rma_open.py +++ b/extra/cr50_rma_open/cr50_rma_open.py @@ -13,6 +13,10 @@ import subprocess import sys import time +SCRIPT_VERSION = 1 +CCD_IS_UNRESTRICTED = 1 << 0 +WP_IS_DISABLED = 1 << 1 +RMA_OPENED = CCD_IS_UNRESTRICTED | WP_IS_DISABLED URL = 'https://www.google.com/chromeos/partner/console/cr50reset?' \ 'challenge=%s&hwid=%s' RMA_SUPPORT = '0.3.3' @@ -43,6 +47,11 @@ challenge url Go to the URL from by that command to generate an authcode. Once you have the authcode, you can use it to open cr50. sudo python cr50_rma_open.py -a $AUTHCODE + +If for some reason hardware write protect doesn't get disabled during rma +open or gets enabled at some point the script can be used to disable +write protect. + sudo python cr50_rma_open.py -w """ DEBUG_MISSING_USB = """ @@ -105,6 +114,10 @@ parser = argparse.ArgumentParser( description=HELP_INFO, formatter_class=argparse.RawTextHelpFormatter) parser.add_argument('-g', '--generate_challenge', action='store_true', help='Generate Cr50 challenge. Must be used in combination with -i') +parser.add_argument('-p', '--print_caps', action='store_true', + help='Print the ccd output when checking the capabilities') +parser.add_argument('-w', '--wp_disable', action='store_true', + help='Disable write protect') parser.add_argument('-c', '--check_connection', action='store_true', help='Check cr50 console connection works') parser.add_argument('-s', '--serialname', type=str, default='', @@ -127,7 +140,8 @@ def info(string): class RMAOpen(object): """Used to find the cr50 console and run RMA open""" - def __init__(self, device=None, usb_serial=None): + def __init__(self, device=None, usb_serial=None, print_caps=False): + self.print_caps = print_caps if device: self.set_cr50_device(device) else: @@ -136,6 +150,7 @@ class RMAOpen(object): self.check_version() self.print_platform_info() info('Cr50 setup ok') + self.update_ccd_state() def set_cr50_device(self, device): @@ -205,49 +220,73 @@ class RMAOpen(object): def try_authcode(self, authcode): - """Try opening cr50 with the authcode""" + """Try opening cr50 with the authcode + + Raises: + ValueError if there was no authcode match and ccd isn't open + """ # rma_auth may cause the system to reboot. Don't wait to read all that # output. Read the first 300 bytes and call it a day. output = self.send_cmd_get_output('rma_auth ' + authcode, nbytes=300) print 'CR50 RESPONSE:', output print 'waiting for cr50 reboot' # Cr50 may be rebooting. Wait a bit - time.sleep(3) - self.check_ccd_settings('process_response: success!' in output) + time.sleep(5) + # Update the ccd state after the authcode attempt + self.update_ccd_state() + + authcode_match = 'process_response: success!' in output + if not self.check(CCD_IS_UNRESTRICTED): + if not authcode_match: + debug(DEBUG_AUTHCODE_MISMATCH) + message = 'Authcode mismatch. Check args and url' + else: + message = 'Could not set all capability privileges to Always' + raise ValueError(message) + + def wp_is_force_disabled(self): + """Returns True if write protect is forced disabled""" + output = self.send_cmd_get_output('wp') + wp_state = output.split('Flash WP:', 1)[-1].split('\n', 1)[0].strip() + info('wp: ' + wp_state) + return wp_state == 'forced disabled' - def ccd_is_closed(self, debug=False): + + def ccd_is_restricted(self): """Returns True if any of the capabilities are still restricted""" output = self.send_cmd_get_output('ccd') if 'Capabilities' not in output: raise ValueError('Could not get ccd output') - if debug: + if self.print_caps: print 'CURRENT CCD SETTINGS:\n', output - is_closed = 'IfOpened' in output or 'IfUnlocked' in output - if not is_closed: - info('Cr50 ccd is Open. RMA Open complete') - return is_closed + restricted = 'IfOpened' in output or 'IfUnlocked' in output + info('ccd: ' + ('Restricted' if restricted else 'Unrestricted')) + return restricted - def check_ccd_settings(self, authcode_match): - """Raise an error if Cr50 CCD is not open + def update_ccd_state(self): + """Get the wp and ccd state from cr50. Save it in _ccd_state""" + self._ccd_state = 0 + if not self.ccd_is_restricted(): + self._ccd_state |= CCD_IS_UNRESTRICTED + if self.wp_is_force_disabled(): + self._ccd_state |= WP_IS_DISABLED - Choose the error and debug messages based on if Cr50 successfully - matched the authcode. - Args: - authcode_match: True if Cr50 successfully processed the authcode. + def check(self, setting): + """Returns true if the all of the 1s in setting are 1 in _ccd_state""" + return self._ccd_state & setting == setting - Raises: - ValueError if 'ccd' does shows any capabilities are restricted. - """ - if self.ccd_is_closed(debug=True): - if not authcode_match: - debug(DEBUG_AUTHCODE_MISMATCH) - raise ValueError('Authcode mismatch. Check args and url') - else: - raise ValueError('Could not set all capability privileges to ' - 'Always') + + def wp_disable(self): + """Disable write protect""" + print 'Disabling write protect' + self.send_cmd_get_output('wp disable') + # Update the state after attempting to disable write protect + self.update_ccd_state() + if not self.check(WP_IS_DISABLED): + raise ValueError('Could not disable write protect') def check_version(self): @@ -357,19 +396,44 @@ class RMAOpen(object): def main(): args = parser.parse_args() + tried_authcode = False + info('Running cr50_rma_open version %s' % SCRIPT_VERSION) - cr50_rma_open = RMAOpen(args.device, args.serialname) - if args.check_connection or not cr50_rma_open.ccd_is_closed(): + cr50_rma_open = RMAOpen(args.device, args.serialname, args.print_caps) + if args.check_connection: sys.exit(0) - elif args.authcode: - info('Using authcode: ' + args.authcode) - cr50_rma_open.try_authcode(args.authcode) - info('Successfully ran RMA Open') - elif args.generate_challenge: - if not args.hwid: - debug('--hwid necessary to generate challenge url') + + if not cr50_rma_open.check(CCD_IS_UNRESTRICTED): + if args.generate_challenge: + if not args.hwid: + debug('--hwid necessary to generate challenge url') + sys.exit(0) + cr50_rma_open.generate_challenge_url(args.hwid) sys.exit(0) - cr50_rma_open.generate_challenge_url(args.hwid) + elif args.authcode: + info('Using authcode: ' + args.authcode) + ccd_state = cr50_rma_open.try_authcode(args.authcode) + tried_authcode = True + + if not cr50_rma_open.check(WP_IS_DISABLED) and (tried_authcode or + args.wp_disable): + if not cr50_rma_open.check(CCD_IS_UNRESTRICTED): + raise ValueError("Can't disable write protect unless ccd is " + "open. Run through the rma open process first") + if tried_authcode: + debug("It's weird rma open didn't disable write protect. Trying to " + "disable it manually") + cr50_rma_open.wp_disable() + + if not cr50_rma_open.check(CCD_IS_UNRESTRICTED): + print 'CCD is still restricted.' + print 'Run cr50_rma_open.py -g -i $HWID to generate a url' + print 'Run cr50_rma_open.py -a $AUTHCODE to open cr50 with an authcode' + elif not cr50_rma_open.check(WP_IS_DISABLED): + print 'WP is still enabled.' + print 'Run cr50_rma_open.py -w to disable write protect' + if cr50_rma_open.check(RMA_OPENED): + info('RMA Open complete') if __name__ == "__main__": main() |