summaryrefslogtreecommitdiffstats
path: root/update_metadata.proto
blob: 7e8e7d4fe4775406753c9b38674156b693e8d540 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
//
// Copyright (C) 2010 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

// Update file format: An update file contains all the operations needed
// to update a system to a specific version. It can be a full payload which
// can update from any version, or a delta payload which can only update
// from a specific version.
// The update format is represented by this struct pseudocode:
// struct delta_update_file {
//   char magic[4] = "CrAU";
//   uint64 file_format_version;  // payload major version
//   uint64 manifest_size;  // Size of protobuf DeltaArchiveManifest
//
//   // Only present if format_version >= 2:
//   uint32 metadata_signature_size;
//
//   // The DeltaArchiveManifest protobuf serialized, not compressed.
//   char manifest[manifest_size];
//
//   // The signature of the metadata (from the beginning of the payload up to
//   // this location, not including the signature itself). This is a serialized
//   // Signatures message.
//   char metadata_signature_message[metadata_signature_size];
//
//   // Data blobs for files, no specific format. The specific offset
//   // and length of each data blob is recorded in the DeltaArchiveManifest.
//   struct {
//     char data[];
//   } blobs[];
//
//   // The signature of the entire payload, everything up to this location,
//   // except that metadata_signature_message is skipped to simplify signing
//   // process. These two are not signed:
//   uint64 payload_signatures_message_size;
//   // This is a serialized Signatures message.
//   char payload_signatures_message[payload_signatures_message_size];
//
// };

// The DeltaArchiveManifest protobuf is an ordered list of InstallOperation
// objects. These objects are stored in a linear array in the
// DeltaArchiveManifest. Each operation is applied in order by the client.

// The DeltaArchiveManifest also contains the initial and final
// checksums for the device.

// The client will perform each InstallOperation in order, beginning even
// before the entire delta file is downloaded (but after at least the
// protobuf is downloaded). The types of operations are explained:
// - REPLACE: Replace the dst_extents on the drive with the attached data,
//   zero padding out to block size.
// - REPLACE_BZ: bzip2-uncompress the attached data and write it into
//   dst_extents on the drive, zero padding to block size.
// - MOVE: Copy the data in src_extents to dst_extents. Extents may overlap,
//   so it may be desirable to read all src_extents data into memory before
//   writing it out. (deprecated)
// - SOURCE_COPY: Copy the data in src_extents in the old partition to
//   dst_extents in the new partition. There's no overlapping of data because
//   the extents are in different partitions.
// - BSDIFF: Read src_length bytes from src_extents into memory, perform
//   bspatch with attached data, write new data to dst_extents, zero padding
//   to block size. (deprecated)
// - SOURCE_BSDIFF: Read the data in src_extents in the old partition, perform
//   bspatch with the attached data and write the new data to dst_extents in the
//   new partition.
// - ZERO: Write zeros to the destination dst_extents.
// - DISCARD: Discard the destination dst_extents blocks on the physical medium.
//   the data read from those block is undefined.
// - REPLACE_XZ: Replace the dst_extents with the contents of the attached
//   xz file after decompression. The xz file should only use crc32 or no crc at
//   all to be compatible with xz-embedded.
// - PUFFDIFF: Read the data in src_extents in the old partition, perform
//   puffpatch with the attached data and write the new data to dst_extents in
//   the new partition.
//
// The operations allowed in the payload (supported by the client) depend on the
// major and minor version. See InstallOperation.Type below for details.

syntax = "proto2";

package chromeos_update_engine;
option optimize_for = LITE_RUNTIME;

// Data is packed into blocks on disk, always starting from the beginning
// of the block. If a file's data is too large for one block, it overflows
// into another block, which may or may not be the following block on the
// physical partition. An ordered list of extents is another
// representation of an ordered list of blocks. For example, a file stored
// in blocks 9, 10, 11, 2, 18, 12 (in that order) would be stored in
// extents { {9, 3}, {2, 1}, {18, 1}, {12, 1} } (in that order).
// In general, files are stored sequentially on disk, so it's more efficient
// to use extents to encode the block lists (this is effectively
// run-length encoding).
// A sentinel value (kuint64max) as the start block denotes a sparse-hole
// in a file whose block-length is specified by num_blocks.

message Extent {
  optional uint64 start_block = 1;
  optional uint64 num_blocks = 2;
}

// Signatures: Updates may be signed by the OS vendor. The client verifies
// an update's signature by hashing the entire download. The section of the
// download that contains the signature is at the end of the file, so when
// signing a file, only the part up to the signature part is signed.
// Then, the client looks inside the download's Signatures message for a
// Signature message that it knows how to handle. Generally, a client will
// only know how to handle one type of signature, but an update may contain
// many signatures to support many different types of client. Then client
// selects a Signature message and uses that, along with a known public key,
// to verify the download. The public key is expected to be part of the
// client.

message Signatures {
  message Signature {
    optional uint32 version = 1;
    optional bytes data = 2;
  }
  repeated Signature signatures = 1;
}

message PartitionInfo {
  optional uint64 size = 1;
  optional bytes hash = 2;
}

// Describe an image we are based on in a human friendly way.
// Examples:
//   dev-channel, x86-alex, 1.2.3, mp-v3
//   nplusone-channel, x86-alex, 1.2.4, mp-v3, dev-channel, 1.2.3
//
// All fields will be set, if this message is present.
message ImageInfo {
  optional string board = 1;
  optional string key = 2;
  optional string channel = 3;
  optional string version = 4;

  // If these values aren't present, they should be assumed to match
  // the equivalent value above. They are normally only different for
  // special image types such as nplusone images.
  optional string build_channel = 5;
  optional string build_version = 6;
}

message InstallOperation {
  enum Type {
    REPLACE = 0;  // Replace destination extents w/ attached data
    REPLACE_BZ = 1;  // Replace destination extents w/ attached bzipped data
    MOVE = 2 [deprecated = true];  // Move source extents to destination extents
    BSDIFF = 3 [deprecated = true];  // The data is a bsdiff binary diff

    // On minor version 2 or newer, these operations are supported:
    SOURCE_COPY = 4; // Copy from source to target partition
    SOURCE_BSDIFF = 5; // Like BSDIFF, but read from source partition

    // On minor version 3 or newer and on major version 2 or newer, these
    // operations are supported:
    REPLACE_XZ = 8; // Replace destination extents w/ attached xz data.

    // On minor version 4 or newer, these operations are supported:
    ZERO = 6;  // Write zeros in the destination.
    DISCARD = 7;  // Discard the destination blocks, reading as undefined.
    BROTLI_BSDIFF = 10;  // Like SOURCE_BSDIFF, but compressed with brotli.

    // On minor version 5 or newer, these operations are supported:
    PUFFDIFF = 9;  // The data is in puffdiff format.
  }
  required Type type = 1;

  // Only minor version 6 or newer support 64 bits |data_offset| and
  // |data_length|, older client will read them as uint32.
  // The offset into the delta file (after the protobuf)
  // where the data (if any) is stored
  optional uint64 data_offset = 2;
  // The length of the data in the delta file
  optional uint64 data_length = 3;

  // Ordered list of extents that are read from (if any) and written to.
  repeated Extent src_extents = 4;
  // Byte length of src, equal to the number of blocks in src_extents *
  // block_size. It is used for BSDIFF and SOURCE_BSDIFF, because we need to
  // pass that external program the number of bytes to read from the blocks we
  // pass it.  This is not used in any other operation.
  optional uint64 src_length = 5;

  repeated Extent dst_extents = 6;
  // Byte length of dst, equal to the number of blocks in dst_extents *
  // block_size. Used for BSDIFF and SOURCE_BSDIFF, but not in any other
  // operation.
  optional uint64 dst_length = 7;

  // Optional SHA 256 hash of the blob associated with this operation.
  // This is used as a primary validation for http-based downloads and
  // as a defense-in-depth validation for https-based downloads. If
  // the operation doesn't refer to any blob, this field will have
  // zero bytes.
  optional bytes data_sha256_hash = 8;

  // Indicates the SHA 256 hash of the source data referenced in src_extents at
  // the time of applying the operation. If present, the update_engine daemon
  // MUST read and verify the source data before applying the operation.
  optional bytes src_sha256_hash = 9;
}

// Describes the update to apply to a single partition.
message PartitionUpdate {
  // A platform-specific name to identify the partition set being updated. For
  // example, in Chrome OS this could be "ROOT" or "KERNEL".
  required string partition_name = 1;

  // Whether this partition carries a filesystem with post-install program that
  // must be run to finalize the update process. See also |postinstall_path| and
  // |filesystem_type|.
  optional bool run_postinstall = 2;

  // The path of the executable program to run during the post-install step,
  // relative to the root of this filesystem. If not set, the default "postinst"
  // will be used. This setting is only used when |run_postinstall| is set and
  // true.
  optional string postinstall_path = 3;

  // The filesystem type as passed to the mount(2) syscall when mounting the new
  // filesystem to run the post-install program. If not set, a fixed list of
  // filesystems will be attempted. This setting is only used if
  // |run_postinstall| is set and true.
  optional string filesystem_type = 4;

  // If present, a list of signatures of the new_partition_info.hash signed with
  // different keys. If the update_engine daemon requires vendor-signed images
  // and has its public key installed, one of the signatures should be valid
  // for /postinstall to run.
  repeated Signatures.Signature new_partition_signature = 5;

  optional PartitionInfo old_partition_info = 6;
  optional PartitionInfo new_partition_info = 7;

  // The list of operations to be performed to apply this PartitionUpdate. The
  // associated operation blobs (in operations[i].data_offset, data_length)
  // should be stored contiguously and in the same order.
  repeated InstallOperation operations = 8;

  // Whether a failure in the postinstall step for this partition should be
  // ignored.
  optional bool postinstall_optional = 9;

  // On minor version 6 or newer, these fields are supported:

  // The extent for data covered by verity hash tree.
  optional Extent hash_tree_data_extent = 10;

  // The extent to store verity hash tree.
  optional Extent hash_tree_extent = 11;

  // The hash algorithm used in verity hash tree.
  optional string hash_tree_algorithm = 12;

  // The salt used for verity hash tree.
  optional bytes hash_tree_salt = 13;

  // The extent for data covered by FEC.
  optional Extent fec_data_extent = 14;

  // The extent to store FEC.
  optional Extent fec_extent = 15;

  // The number of FEC roots.
  optional uint32 fec_roots = 16 [default = 2];
}

message DynamicPartitionGroup {
  // Name of the group.
  required string name = 1;

  // Maximum size of the group. The sum of sizes of all partitions in the group
  // must not exceed the maximum size of the group.
  optional uint64 size = 2;

  // A list of partitions that belong to the group.
  repeated string partition_names = 3;
}

// Metadata related to all dynamic partitions.
message DynamicPartitionMetadata {
  // All updatable groups present in |partitions| of this DeltaArchiveManifest.
  // - If an updatable group is on the device but not in the manifest, it is
  //   not updated. Hence, the group will not be resized, and partitions cannot
  //   be added to or removed from the group.
  // - If an updatable group is in the manifest but not on the device, the group
  //   is added to the device.
  repeated DynamicPartitionGroup groups = 1;
}

message DeltaArchiveManifest {
  // Only present in major version = 1. List of install operations for the
  // kernel and rootfs partitions. For major version = 2 see the |partitions|
  // field.
  repeated InstallOperation install_operations = 1;
  repeated InstallOperation kernel_install_operations = 2;

  // (At time of writing) usually 4096
  optional uint32 block_size = 3 [default = 4096];

  // If signatures are present, the offset into the blobs, generally
  // tacked onto the end of the file, and the length. We use an offset
  // rather than a bool to allow for more flexibility in future file formats.
  // If either is absent, it means signatures aren't supported in this
  // file.
  optional uint64 signatures_offset = 4;
  optional uint64 signatures_size = 5;

  // Only present in major version = 1. Partition metadata used to validate the
  // update. For major version = 2 see the |partitions| field.
  optional PartitionInfo old_kernel_info = 6;
  optional PartitionInfo new_kernel_info = 7;
  optional PartitionInfo old_rootfs_info = 8;
  optional PartitionInfo new_rootfs_info = 9;

  // old_image_info will only be present for delta images.
  optional ImageInfo old_image_info = 10;

  optional ImageInfo new_image_info = 11;

  // The minor version, also referred as "delta version", of the payload.
  // Minor version 0 is full payload, everything else is delta payload.
  optional uint32 minor_version = 12 [default = 0];

  // Only present in major version >= 2. List of partitions that will be
  // updated, in the order they will be updated. This field replaces the
  // |install_operations|, |kernel_install_operations| and the
  // |{old,new}_{kernel,rootfs}_info| fields used in major version = 1. This
  // array can have more than two partitions if needed, and they are identified
  // by the partition name.
  repeated PartitionUpdate partitions = 13;

  // The maximum timestamp of the OS allowed to apply this payload.
  // Can be used to prevent downgrading the OS.
  optional int64 max_timestamp = 14;

  // Metadata related to all dynamic partitions.
  optional DynamicPartitionMetadata dynamic_partition_metadata = 15;
}