blob: d7a60e93a2a4f326b9f458ac35c66abf7b846ab7 [file] [log] [blame]
Jon Salzf10ef792014-04-01 14:25:36 +08001#!/usr/bin/python
2#
3# Copyright (c) 2014 The Chromium OS Authors. All rights reserved.
4# Use of this source code is governed by a BSD-style license that can be
5# found in the LICENSE file.
6
7
8"""A command-line tool for reg code handling."""
9
10
Jon Salz1c954152014-04-08 11:48:39 +080011import binascii
Jon Salz2fc97202014-04-21 16:42:59 +080012import logging
Jon Salz1c954152014-04-08 11:48:39 +080013import random
14import sys
15
Jon Salzf10ef792014-04-01 14:25:36 +080016import factory_common # pylint: disable=W0611
17from cros.factory.hacked_argparse import CmdArg, Command, ParseCmdline
Jon Salz1c954152014-04-08 11:48:39 +080018from cros.factory.proto import reg_code_pb2
Jon Salz2fc97202014-04-21 16:42:59 +080019from cros.factory.system import vpd
Jon Salz1c954152014-04-08 11:48:39 +080020from cros.factory.test import registration_codes
Jon Salz2fc97202014-04-21 16:42:59 +080021from cros.factory.test import utils
Jon Salzf10ef792014-04-01 14:25:36 +080022from cros.factory.test.registration_codes import RegistrationCode
Jon Salz2fc97202014-04-21 16:42:59 +080023from cros.factory.tools.build_board import BuildBoard
Jon Salzf10ef792014-04-01 14:25:36 +080024
25
26@Command('decode',
27 CmdArg('regcode', metavar='REGCODE',
28 help='Encoded registration code string'))
29def Decode(options):
30 reg_code = RegistrationCode(options.regcode)
31 if reg_code.proto:
32 print reg_code.proto
33 else:
34 print reg_code
35
36
Jon Salz1c954152014-04-08 11:48:39 +080037@Command(
38 'generate-dummy',
39 CmdArg('--board', '-b', metavar='BOARD', required=True,
40 help=('Board to generate codes for. This must be exactly the '
41 'same as the HWID board name, except lowercase. For '
42 'boards with variants (like "daisy_spring"), use only '
43 'the variant name ("spring").')),
44 CmdArg('--type', '-t', metavar='TYPE', required=True,
45 choices=['unique', 'group'],
46 help='The type of code to generate (choices: %(choices)s)'),
47 CmdArg('--seed', '-s', metavar='INT', type=int, default=None,
48 help='Seed to use for pseudo-random payload; defaults to clock'))
49def GenerateDummy(options):
50 print ('*** This may be used only to generate a code for testing, '
51 'not for a real device.')
52 yes_no = raw_input('*** Are you OK with that? (yes/no) ')
53 if yes_no != 'yes':
54 print 'Aborting.'
55 sys.exit(1)
56
57 random.seed(options.seed)
58 proto = reg_code_pb2.RegCode()
59 proto.content.code_type = (reg_code_pb2.UNIQUE_CODE
60 if options.type == 'unique'
61 else reg_code_pb2.GROUP_CODE)
62
63 # Use this weird magic string for the first 16 characters to make it
64 # obvious that this is a dummy code. (Base64-encoding this string
65 # results in a reg code that looks like
66 # '=CiwKIP//////TESTING///////'...)
67 proto.content.code = (
68 '\xff\xff\xff\xff\xffLD\x93 \xd1\xbf\xff\xff\xff\xff\xff' + "".join(
69 chr(random.getrandbits(8))
70 for i in range(registration_codes.REGISTRATION_CODE_PAYLOAD_BYTES - 16)))
71 proto.content.device = options.board.lower()
72 proto.checksum = (
73 binascii.crc32(proto.content.SerializeToString()) & 0xFFFFFFFF)
74
75 encoded_string = '=' + binascii.b2a_base64(proto.SerializeToString()).strip()
76
77 # Make sure the string can be parsed as a sanity check (this will catch,
78 # e.g., invalid device names)
79 reg_code = RegistrationCode(encoded_string)
80 print
81 print reg_code.proto
82 print encoded_string
83
84
Jon Salz2fc97202014-04-21 16:42:59 +080085@Command(
86 'check',
87 CmdArg(
88 '--unique-code', '-u', metavar='UNIQUE_CODE',
89 help='Unique/user code to check (default: ubind_attribute RW VPD value)'),
90 CmdArg(
91 '--group-code', '-g', metavar='GROUP_CODE',
92 help='Group code to check (default: gbind_attribute RW VPD value)'),
93 CmdArg(
94 '--board', '-b', metavar='BOARD',
95 help='Board to check (default: from .default_board or lsb-release)'))
96def Check(options):
97 if not options.board:
98 options.board = BuildBoard().short_name
99 logging.info('Device name: %s', options.board)
100
101 rw_vpd = None
102 success = True
103
104 for code_type, vpd_attribute, code in (
105 (RegistrationCode.Type.UNIQUE_CODE,
106 'ubind_attribute', options.unique_code),
107 (RegistrationCode.Type.GROUP_CODE,
108 'gbind_attribute', options.group_code)):
109
110 if not code:
111 if rw_vpd is None:
112 if utils.in_chroot():
113 sys.stderr.write('error: cannot read VPD from chroot; use -u/-g\n')
114 sys.exit(1)
115
116 rw_vpd = vpd.rw.GetAll()
117 code = rw_vpd.get(vpd_attribute)
118 if not code:
119 sys.stderr.write('error: %s is not present in RW VPD\n' %
120 vpd_attribute)
121 sys.exit(1)
122
123 try:
124 registration_codes.CheckRegistrationCode(code, code_type, options.board)
125 logging.info('%s: success', code_type)
126 except registration_codes.RegistrationCodeException as e:
127 success = False
128 logging.error('%s: failed: %s', code_type, str(e))
129
130 sys.exit(0 if success else 1)
131
132
Jon Salzf10ef792014-04-01 14:25:36 +0800133def main():
Jon Salz2fc97202014-04-21 16:42:59 +0800134 logging.basicConfig(level=logging.INFO)
Jon Salzf10ef792014-04-01 14:25:36 +0800135 options = ParseCmdline('Registration code tool.')
136 options.command(options)
137
138
139if __name__ == '__main__':
140 main()