1// Copyright 2021 The Pigweed Authors 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); you may not 4// use this file except in compliance with the License. You may obtain a copy of 5// the License at 6// 7// https://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12// License for the specific language governing permissions and limitations under 13// the License. 14syntax = "proto3"; 15 16package pw.software_update; 17 18import "pw_protobuf_protos/common.proto"; 19import "pw_tokenizer/proto/options.proto"; 20import "google/protobuf/any.proto"; 21 22message BundledUpdateState { 23 enum Enum { 24 UNKNOWN = 0; // Not an expected state in the OTA system; only for proto. 25 26 // Valid methods in this state: Start() 27 // 28 // Transition: 29 // Start() succeeds --> TRANSFERRING 30 // Start() fails --> FINISHED 31 INACTIVE = 1; 32 33 // Valid methods in this state: GetStatus(), Abort(). 34 // 35 // Transitions: 36 // Transfer completes --> TRANSFERRED 37 // Transfer fails --> FINISHED 38 // Abort() called --> ABORTING 39 TRANSFERRING = 2; 40 41 // Valid methods in this state: GetStatus(), Abort(), Verify(). 42 // 43 // Transitions: 44 // Verify() called --> VERIFYING 45 // Apply() called --> VERIFYING 46 // Abort() called --> ABORTING 47 TRANSFERRED = 3; 48 49 // Valid methods in this state: GetStatus(), Abort(). 50 // 51 // Transitions: 52 // Verifying finished --> VERIFIED 53 // Verifying failed --> FINISHED 54 // Abort() called --> ABORTING 55 VERIFYING = 4; 56 57 // Valid methods in this state: GetStatus(), Abort(), Apply(). 58 // 59 // Transitions: 60 // Apply() called --> APPLYING 61 // Abort() called --> ABORTING 62 VERIFIED = 5; 63 64 // Valid methods in this state: GetStatus(). 65 // 66 // Transitions: 67 // Apply() finished --> FINISHED; may require persisting across a reboot. 68 // Apply() failed --> FINISHED; with error set. 69 APPLYING = 6; 70 71 // Valid methods in this state: GetStatus(). 72 // 73 // Transitions: 74 // Abort finishes --> FINISHED 75 // Abort fails --> FINISHED 76 ABORTING = 7; 77 78 // Valid methods in this state: GetStatus(), Reset(). 79 // 80 // Terminal state indicating a finished update; whether successful or 81 // not. Additional termination information available in completion_state 82 // and possibly note. 83 // 84 // Transitions: 85 // Reset() succeeds --> INACTIVE 86 // Reset() fails --> FINISHED 87 FINISHED = 8; 88 } 89} 90 91message BundledUpdateResult { 92 enum Enum { 93 UNKNOWN = 0; 94 SUCCESS = 1; 95 UNKNOWN_ERROR = 2; 96 ABORTED = 3; 97 TRANSFER_FAILED = 4; 98 VERIFY_FAILED = 5; 99 APPLY_FAILED = 6; 100 } 101} 102 103message BundledUpdateStatus { 104 BundledUpdateState.Enum state = 1; 105 106 optional BundledUpdateResult.Enum result = 2; 107 108 // This is the percentage of estimated progress for the current update 109 // state in hundreths of a percent. (e.g. 5.00% = 500u) 110 optional uint32 current_state_progress_hundreth_percent = 3; 111 112 // If present, the active transfer ID for the update. 113 optional uint32 transfer_id = 4; 114 115 // The name of the update bundle. Not present when in INACTIVE state. This is 116 // useful for enabling resuming of transfers across reboots or disconnects, 117 // without transferring an expensive manifest. 118 optional string bundle_filename = 5; 119 120 // Additional information related to the state may be provided here. 121 // Examples: "Failed verifying: ml_model.bin", "Flash partition couldn't be 122 // acquired and was busy", etc. Can provide more granular information than 123 // just the completion result. 124 optional bytes note = 6 [(tokenizer.format) = TOKENIZATION_OPTIONAL]; 125 126 // Custom application data. 127 optional google.protobuf.Any extended_status = 7; 128} 129 130message StartRequest { 131 // If present, the filename for the staged file. This should persist across 132 // reboots, and will be returned from GetStatus() until either the update 133 // applies or is aborted. 134 optional string bundle_filename = 1; 135} 136 137// TODO(b/235273688): Add documentation and details of the API contract. 138service BundledUpdate { 139 // TODO(keir): Offer GetCurrentManifest & GetStagedManifest() methods that 140 // leverage pw_transfer to upload the manifest off the device, to enable host 141 // logic. 142 143 // Get current status of software update. 144 rpc GetStatus(pw.protobuf.Empty) returns (BundledUpdateStatus); 145 146 // Start a software update. Do any device-specific tasks needed to be ready 147 // for update. Open pw_transfer channel used for staging bundle. 148 // Returned status includes the transfer ID to use for bundle transfer. 149 // 150 // Precondition: Device update state must be INACTIVE. 151 rpc Start(StartRequest) returns (BundledUpdateStatus); 152 153 // Manually set the bundle status as transferred. It can be used to recover 154 // a previously finished transfer or used when transfer happens on a side 155 // channel without involvement of pw_transfer 156 // 157 // Precondition: Device update state must be INACTIVE or TRANSFERRING 158 rpc SetTransferred(pw.protobuf.Empty) returns (BundledUpdateStatus); 159 160 // Verify the bundle in the staging area. Returns immediately, but 161 // verification runs asynchronously. Poll for completion with GetStatus(). 162 // 163 // Precondition: Device update state must be TRANSFERRED. 164 rpc Verify(pw.protobuf.Empty) returns (BundledUpdateStatus); 165 166 // Apply the staged update. The update process will verify the staged bundle 167 // or ensure that it was verified, apply the bundle, and in some cases reboot 168 // the device. During this process, the device may be slow to respond. 169 // 170 // The RPC is async; callers must fetch status with GetStatus(). 171 // 172 // Precondition: Device update state must be TRANSFERRED or VERIFIED. 173 rpc Apply(pw.protobuf.Empty) returns (BundledUpdateStatus); 174 175 // Abort any current software update in progress. 176 // Precondition: Device update state must not be INACTIVE or FINISHED. 177 rpc Abort(pw.protobuf.Empty) returns (BundledUpdateStatus); 178 179 // Reset after a finished update. Device goes into INACTIVE state after. 180 // 181 // Precondition: Device update state must be FINISHED. 182 rpc Reset(pw.protobuf.Empty) returns (BundledUpdateStatus); 183} 184