blob: a0ff2b10e08b4a3c0b8299412791c53dd2df0486 [file] [log] [blame]
Hung-Te Linc83105f2011-03-16 18:38:04 +08001#!/usr/bin/env python
Hung-Te Lin176670f2011-03-30 13:08:50 +08002# Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
Hung-Te Linc83105f2011-03-16 18:38:04 +08003# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
6# THIS FILE IS COPIED FROM AUTOTEST LIBRARY AND FOLLOWING PEP8 CODING STYLE RULE
7# FOR BACKWARD COMPATIBLE, WE'RE NOT CHANGING ITS INDENTATION AND FUNCTION NAMES
8
9"""
10 Chrome OS firmware verification block parser.
11
12 This module helps parsing firmware verification blocks so that we can
13 retrieve the version and other information from a blob.
14
15 See help(unpack_verification_block) for more information.
16
17 ref: src/platform/vboot_reference/firmware/lib/include/vboot_struct.h
18"""
19
20import struct
21import sys
22
23# Constant Definition
Hung-Te Lin56b18402015-01-16 14:52:30 +080024KEY_BLOCK_MAGIC = 'CHROMEOS'
Hung-Te Linc83105f2011-03-16 18:38:04 +080025KEY_BLOCK_MAGIC_SIZE = 8
26KEY_BLOCK_HEADER_VERSION_MAJOR = 2
27KEY_BLOCK_HEADER_VERSION_MINOR = 1
28FIRMWARE_PREAMBLE_HEADER_VERSION_MAJOR = 2
29FIRMWARE_PREAMBLE_HEADER_VERSION_MINOR = 0
30
31
32def unpack_VbKeyBlockHeader(blob, offset=0):
Hung-Te Lin56b18402015-01-16 14:52:30 +080033 """Unpacks a VbKeyBlockHeader from a blob, starting from offset.
Hung-Te Linc83105f2011-03-16 18:38:04 +080034
Hung-Te Lin56b18402015-01-16 14:52:30 +080035 The blob is supposed to be a VBLOCK_A or VBLOCK_A in firmware image.
36 Blob structure:
37 typedef struct VbKeyBlockHeader {
38 uint8_t magic[KEY_BLOCK_MAGIC_SIZE];
39 uint32_t header_version_major;
40 uint32_t header_version_minor;
41 uint64_t key_block_size;
42 ...
43 };
44 """
45 fields = struct.unpack_from('<8sIIQ', blob, offset)
46 names = ('magic', 'header_version_major', 'header_version_minor',
47 'key_block_size')
48 header = dict(zip(names, fields))
49 # check values
50 if header['magic'] != KEY_BLOCK_MAGIC:
51 raise ValueError, 'unknown key block magic: %s' % header['magic']
52 major = header['header_version_major']
53 minor = header['header_version_minor']
54 if (major != KEY_BLOCK_HEADER_VERSION_MAJOR):
55 raise ValueError, 'unknown key block version (%d.%d)' % (major, minor)
56 return header
Hung-Te Linc83105f2011-03-16 18:38:04 +080057
58
59def unpack_VbFirmwarePreambleHeader(blob, offset=0):
Hung-Te Lin56b18402015-01-16 14:52:30 +080060 """Unpacks a VbFirmwarePreambleHeader from a blob, starting from offset.
Hung-Te Linc83105f2011-03-16 18:38:04 +080061
Hung-Te Lin56b18402015-01-16 14:52:30 +080062 The blob is supposed to be located immediately after a VbKeyBlockHeader.
63 (i.e., offset = VbKeyBlockHeader[key_block_size])
64 Blob structure:
65 typedef struct VbFirmwarePreambleHeader {
66 uint64_t preamble_size;
67 struct VbSignature preamble_signature {
68 uint64_t sig_offset;
69 uint64_t sig_size;
70 uint64_t data_size;
71 };
72 uint32_t header_version_major;
73 uint32_t header_version_minor;
74 uint64_t firmware_version;
75 ...
76 };
77 """
78 fields = struct.unpack_from('<QQQQIIQ', blob, offset)
79 names = ('preamble_size',
80 'sig_offset', 'sig_size', 'data_size',
81 'header_version_major', 'header_version_minor',
82 'firmware_version')
83 header = dict(zip(names, fields))
84 # check values
85 major = header['header_version_major']
86 minor = header['header_version_minor']
87 if major != FIRMWARE_PREAMBLE_HEADER_VERSION_MAJOR:
88 raise ValueError, 'unknown preamble version: (%d.%d)' % (major, minor)
89 return header
Hung-Te Linc83105f2011-03-16 18:38:04 +080090
91
92def unpack_verification_block(blob, offset=0):
Hung-Te Lin56b18402015-01-16 14:52:30 +080093 """Unpacks a Chrome OS verification block.
Hung-Te Linc83105f2011-03-16 18:38:04 +080094
Hung-Te Lin56b18402015-01-16 14:52:30 +080095 Returns a dictionary of VbKeyBlockHeader and VbFirmwarePreambleHeader.
Hung-Te Linc83105f2011-03-16 18:38:04 +080096
Hung-Te Lin56b18402015-01-16 14:52:30 +080097 Use help(unpack_VbKeyBlockHeader) and help(unpack_VbFirmwarePreambleHeader)
98 for more detail information.
99 """
100 result = {}
101 result['VbKeyBlockHeader'] = unpack_VbKeyBlockHeader(blob, offset)
102 result['VbFirmwarePreambleHeader'] = unpack_VbFirmwarePreambleHeader(
103 blob, result['VbKeyBlockHeader']['key_block_size'])
104 return result
Hung-Te Linc83105f2011-03-16 18:38:04 +0800105
106
107# -----------------------------------------------------------------------------
108
109
110def test_report_vblock_info(blob, offset=0):
Hung-Te Lin56b18402015-01-16 14:52:30 +0800111 """ Reports the information of a vblock blob. """
112 kb_header = unpack_VbKeyBlockHeader(blob, offset)
113 print '-- VbKeyBlockHeader --'
114 for name, value in kb_header.items():
115 print name, ':', value
116 preamble = unpack_VbFirmwarePreambleHeader(blob,
117 kb_header['key_block_size'])
118 print '-- VbFirmwarePreambleHeader --'
119 for name, value in preamble.items():
120 print name, ':', value
121 print '-- END --'
Hung-Te Linc83105f2011-03-16 18:38:04 +0800122
123
124# main stub
Hung-Te Lin56b18402015-01-16 14:52:30 +0800125if __name__ == '__main__':
126 # when running in command line, try to report blob in the parameters
127 for filename in sys.argv[1:]:
128 test_report_vblock_info(open(filename, 'rb').read())