xref: /aosp_15_r20/system/nvram/messages/io.cpp (revision 7ba4dab5cc5e3c8f3eb594dcf3b33f99d9214aee)
1*7ba4dab5SXin Li /*
2*7ba4dab5SXin Li  * Copyright (C) 2016 The Android Open Source Project
3*7ba4dab5SXin Li  *
4*7ba4dab5SXin Li  * Licensed under the Apache License, Version 2.0 (the "License");
5*7ba4dab5SXin Li  * you may not use this file except in compliance with the License.
6*7ba4dab5SXin Li  * You may obtain a copy of the License at
7*7ba4dab5SXin Li  *
8*7ba4dab5SXin Li  *      http://www.apache.org/licenses/LICENSE-2.0
9*7ba4dab5SXin Li  *
10*7ba4dab5SXin Li  * Unless required by applicable law or agreed to in writing, software
11*7ba4dab5SXin Li  * distributed under the License is distributed on an "AS IS" BASIS,
12*7ba4dab5SXin Li  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*7ba4dab5SXin Li  * See the License for the specific language governing permissions and
14*7ba4dab5SXin Li  * limitations under the License.
15*7ba4dab5SXin Li  */
16*7ba4dab5SXin Li 
17*7ba4dab5SXin Li #include <nvram/messages/io.h>
18*7ba4dab5SXin Li 
19*7ba4dab5SXin Li extern "C" {
20*7ba4dab5SXin Li #include <string.h>
21*7ba4dab5SXin Li }
22*7ba4dab5SXin Li 
23*7ba4dab5SXin Li #include <nvram/messages/compiler.h>
24*7ba4dab5SXin Li 
25*7ba4dab5SXin Li namespace nvram {
26*7ba4dab5SXin Li namespace {
27*7ba4dab5SXin Li 
28*7ba4dab5SXin Li template <typename T>
min(T x,T y)29*7ba4dab5SXin Li T min(T x, T y) {
30*7ba4dab5SXin Li   return x < y ? x : y;
31*7ba4dab5SXin Li }
32*7ba4dab5SXin Li 
33*7ba4dab5SXin Li template <typename T>
max(T x,T y)34*7ba4dab5SXin Li T max(T x, T y) {
35*7ba4dab5SXin Li   return x > y ? x : y;
36*7ba4dab5SXin Li }
37*7ba4dab5SXin Li 
38*7ba4dab5SXin Li // Encodes |value| in varint format and writes the result to |stream|.
EncodeVarint(OutputStreamBuffer * stream,uint64_t value)39*7ba4dab5SXin Li bool EncodeVarint(OutputStreamBuffer* stream, uint64_t value) {
40*7ba4dab5SXin Li   do {
41*7ba4dab5SXin Li     uint8_t byte = (value & 0x7f) | (((value >> 7) == 0) ? 0x00 : 0x80);
42*7ba4dab5SXin Li     if (!stream->WriteByte(byte)) {
43*7ba4dab5SXin Li       return false;
44*7ba4dab5SXin Li     }
45*7ba4dab5SXin Li     value >>= 7;
46*7ba4dab5SXin Li   } while (value != 0);
47*7ba4dab5SXin Li   return true;
48*7ba4dab5SXin Li }
49*7ba4dab5SXin Li 
50*7ba4dab5SXin Li // Read a varint-encoded number from stream, decode it and store the result in
51*7ba4dab5SXin Li // |value|.
DecodeVarint(InputStreamBuffer * stream_buffer,uint64_t * value)52*7ba4dab5SXin Li bool DecodeVarint(InputStreamBuffer* stream_buffer, uint64_t* value) {
53*7ba4dab5SXin Li   // Maximum number of bytes required to encode an |uint64_t| as varint. Each
54*7ba4dab5SXin Li   // byte in a varint has 7 payload bytes, so encoding 64 bits yields at most 10
55*7ba4dab5SXin Li   // bytes.
56*7ba4dab5SXin Li   static constexpr int kMaxVarintBytes = 10;
57*7ba4dab5SXin Li 
58*7ba4dab5SXin Li   *value = 0;
59*7ba4dab5SXin Li   for (int i = 0; i < kMaxVarintBytes; ++i) {
60*7ba4dab5SXin Li     uint8_t byte = 0;
61*7ba4dab5SXin Li     if (!stream_buffer->ReadByte(&byte)) {
62*7ba4dab5SXin Li       return false;
63*7ba4dab5SXin Li     }
64*7ba4dab5SXin Li     *value |= static_cast<uint64_t>(byte & 0x7f) << (i * 7);
65*7ba4dab5SXin Li     if ((byte & 0x80) == 0) {
66*7ba4dab5SXin Li       return true;
67*7ba4dab5SXin Li     }
68*7ba4dab5SXin Li   }
69*7ba4dab5SXin Li   return false;
70*7ba4dab5SXin Li }
71*7ba4dab5SXin Li 
72*7ba4dab5SXin Li }  // namespace
73*7ba4dab5SXin Li 
InputStreamBuffer(const void * data,size_t size)74*7ba4dab5SXin Li InputStreamBuffer::InputStreamBuffer(const void* data, size_t size)
75*7ba4dab5SXin Li     : InputStreamBuffer(data, static_cast<const uint8_t*>(data) + size) {}
76*7ba4dab5SXin Li 
InputStreamBuffer(const void * start,const void * end)77*7ba4dab5SXin Li InputStreamBuffer::InputStreamBuffer(const void* start, const void* end)
78*7ba4dab5SXin Li     : pos_(static_cast<const uint8_t*>(start)),
79*7ba4dab5SXin Li       end_(static_cast<const uint8_t*>(end)) {
80*7ba4dab5SXin Li   NVRAM_CHECK(pos_ <= end_);
81*7ba4dab5SXin Li }
82*7ba4dab5SXin Li 
Done()83*7ba4dab5SXin Li bool InputStreamBuffer::Done() {
84*7ba4dab5SXin Li   return pos_ >= end_ && !Advance();
85*7ba4dab5SXin Li }
86*7ba4dab5SXin Li 
Read(void * data,size_t size)87*7ba4dab5SXin Li bool InputStreamBuffer::Read(void* data, size_t size) {
88*7ba4dab5SXin Li   uint8_t* buffer = static_cast<uint8_t*>(data);
89*7ba4dab5SXin Li   NVRAM_CHECK(pos_ <= end_);
90*7ba4dab5SXin Li   while (size > static_cast<size_t>(end_ - pos_)) {
91*7ba4dab5SXin Li     memcpy(buffer, pos_, end_ - pos_);
92*7ba4dab5SXin Li     buffer += end_ - pos_;
93*7ba4dab5SXin Li     size -= end_ - pos_;
94*7ba4dab5SXin Li     pos_ = end_;
95*7ba4dab5SXin Li     if (!Advance()) {
96*7ba4dab5SXin Li       return false;
97*7ba4dab5SXin Li     }
98*7ba4dab5SXin Li     NVRAM_CHECK(pos_ < end_);
99*7ba4dab5SXin Li   }
100*7ba4dab5SXin Li   memcpy(buffer, pos_, size);
101*7ba4dab5SXin Li   pos_ += size;
102*7ba4dab5SXin Li   return true;
103*7ba4dab5SXin Li }
104*7ba4dab5SXin Li 
ReadByte(uint8_t * byte)105*7ba4dab5SXin Li bool InputStreamBuffer::ReadByte(uint8_t* byte) {
106*7ba4dab5SXin Li   if (pos_ >= end_) {
107*7ba4dab5SXin Li     if (!Advance()) {
108*7ba4dab5SXin Li       return false;
109*7ba4dab5SXin Li     }
110*7ba4dab5SXin Li     NVRAM_CHECK(pos_ < end_);
111*7ba4dab5SXin Li   }
112*7ba4dab5SXin Li   *byte = *pos_;
113*7ba4dab5SXin Li   ++pos_;
114*7ba4dab5SXin Li   return true;
115*7ba4dab5SXin Li }
116*7ba4dab5SXin Li 
Skip(size_t size)117*7ba4dab5SXin Li bool InputStreamBuffer::Skip(size_t size) {
118*7ba4dab5SXin Li   NVRAM_CHECK(pos_ <= end_);
119*7ba4dab5SXin Li   while (size > static_cast<size_t>(end_ - pos_)) {
120*7ba4dab5SXin Li     size -= end_ - pos_;
121*7ba4dab5SXin Li     pos_ = end_;
122*7ba4dab5SXin Li     if (!Advance()) {
123*7ba4dab5SXin Li       return false;
124*7ba4dab5SXin Li     }
125*7ba4dab5SXin Li     NVRAM_CHECK(pos_ < end_);
126*7ba4dab5SXin Li   }
127*7ba4dab5SXin Li   pos_ += size;
128*7ba4dab5SXin Li   return true;
129*7ba4dab5SXin Li }
130*7ba4dab5SXin Li 
Advance()131*7ba4dab5SXin Li bool InputStreamBuffer::Advance() {
132*7ba4dab5SXin Li   return false;
133*7ba4dab5SXin Li }
134*7ba4dab5SXin Li 
NestedInputStreamBuffer(InputStreamBuffer * delegate,size_t size)135*7ba4dab5SXin Li NestedInputStreamBuffer::NestedInputStreamBuffer(InputStreamBuffer* delegate,
136*7ba4dab5SXin Li                                                  size_t size)
137*7ba4dab5SXin Li     : InputStreamBuffer(delegate->pos_, ClampEnd(delegate, size)),
138*7ba4dab5SXin Li       delegate_(delegate),
139*7ba4dab5SXin Li       remaining_(size) {}
140*7ba4dab5SXin Li 
Advance()141*7ba4dab5SXin Li bool NestedInputStreamBuffer::Advance() {
142*7ba4dab5SXin Li   remaining_ -= end_ - delegate_->pos_;
143*7ba4dab5SXin Li   if (remaining_ == 0) {
144*7ba4dab5SXin Li     delegate_->pos_ = end_;
145*7ba4dab5SXin Li     return false;
146*7ba4dab5SXin Li   }
147*7ba4dab5SXin Li   bool status = delegate_->Advance();
148*7ba4dab5SXin Li   pos_ = delegate_->pos_;
149*7ba4dab5SXin Li   end_ = ClampEnd(delegate_, remaining_);
150*7ba4dab5SXin Li   return status;
151*7ba4dab5SXin Li }
152*7ba4dab5SXin Li 
153*7ba4dab5SXin Li // static
ClampEnd(InputStreamBuffer * delegate,size_t size)154*7ba4dab5SXin Li const uint8_t* NestedInputStreamBuffer::ClampEnd(InputStreamBuffer* delegate,
155*7ba4dab5SXin Li                                                  size_t size) {
156*7ba4dab5SXin Li   NVRAM_CHECK(delegate->pos_ <= delegate->end_);
157*7ba4dab5SXin Li   return size < static_cast<size_t>(delegate->end_ - delegate->pos_)
158*7ba4dab5SXin Li              ? delegate->pos_ + size
159*7ba4dab5SXin Li              : delegate->end_;
160*7ba4dab5SXin Li }
161*7ba4dab5SXin Li 
OutputStreamBuffer(void * data,size_t size)162*7ba4dab5SXin Li OutputStreamBuffer::OutputStreamBuffer(void* data, size_t size)
163*7ba4dab5SXin Li     : OutputStreamBuffer(data, static_cast<uint8_t*>(data) + size) {}
164*7ba4dab5SXin Li 
OutputStreamBuffer(void * start,void * end)165*7ba4dab5SXin Li OutputStreamBuffer::OutputStreamBuffer(void* start, void* end)
166*7ba4dab5SXin Li     : pos_(static_cast<uint8_t*>(start)), end_(static_cast<uint8_t*>(end)) {
167*7ba4dab5SXin Li   NVRAM_CHECK(pos_ <= end_);
168*7ba4dab5SXin Li }
169*7ba4dab5SXin Li 
Done()170*7ba4dab5SXin Li bool OutputStreamBuffer::Done() {
171*7ba4dab5SXin Li   return pos_ >= end_ && !Advance();
172*7ba4dab5SXin Li }
173*7ba4dab5SXin Li 
Write(const void * data,size_t size)174*7ba4dab5SXin Li bool OutputStreamBuffer::Write(const void* data, size_t size) {
175*7ba4dab5SXin Li   const uint8_t* buffer = static_cast<const uint8_t*>(data);
176*7ba4dab5SXin Li   NVRAM_CHECK(pos_ <= end_);
177*7ba4dab5SXin Li   while (size > static_cast<size_t>(end_ - pos_)) {
178*7ba4dab5SXin Li     memcpy(pos_, buffer, end_ - pos_);
179*7ba4dab5SXin Li     buffer += end_ - pos_;
180*7ba4dab5SXin Li     size -= end_ - pos_;
181*7ba4dab5SXin Li     pos_ = end_;
182*7ba4dab5SXin Li     if (!Advance()) {
183*7ba4dab5SXin Li       return false;
184*7ba4dab5SXin Li     }
185*7ba4dab5SXin Li     NVRAM_CHECK(pos_ < end_);
186*7ba4dab5SXin Li   }
187*7ba4dab5SXin Li   memcpy(pos_, buffer, size);
188*7ba4dab5SXin Li   pos_ += size;
189*7ba4dab5SXin Li   return true;
190*7ba4dab5SXin Li }
191*7ba4dab5SXin Li 
WriteByte(uint8_t byte)192*7ba4dab5SXin Li bool OutputStreamBuffer::WriteByte(uint8_t byte) {
193*7ba4dab5SXin Li   if (pos_ >= end_) {
194*7ba4dab5SXin Li     if (!Advance()) {
195*7ba4dab5SXin Li       return false;
196*7ba4dab5SXin Li     }
197*7ba4dab5SXin Li     NVRAM_CHECK(pos_ < end_);
198*7ba4dab5SXin Li   }
199*7ba4dab5SXin Li   *pos_ = byte;
200*7ba4dab5SXin Li   ++pos_;
201*7ba4dab5SXin Li   return true;
202*7ba4dab5SXin Li }
203*7ba4dab5SXin Li 
Advance()204*7ba4dab5SXin Li bool OutputStreamBuffer::Advance() {
205*7ba4dab5SXin Li   return false;
206*7ba4dab5SXin Li }
207*7ba4dab5SXin Li 
CountingOutputStreamBuffer()208*7ba4dab5SXin Li CountingOutputStreamBuffer::CountingOutputStreamBuffer()
209*7ba4dab5SXin Li     : OutputStreamBuffer(scratch_space_, kScratchSpaceSize) {}
210*7ba4dab5SXin Li 
Advance()211*7ba4dab5SXin Li bool CountingOutputStreamBuffer::Advance() {
212*7ba4dab5SXin Li   bytes_written_ += pos_ - scratch_space_;
213*7ba4dab5SXin Li   pos_ = scratch_space_;
214*7ba4dab5SXin Li   end_ = scratch_space_ + kScratchSpaceSize;
215*7ba4dab5SXin Li   return true;
216*7ba4dab5SXin Li }
217*7ba4dab5SXin Li 
218*7ba4dab5SXin Li uint8_t CountingOutputStreamBuffer::scratch_space_[kScratchSpaceSize];
219*7ba4dab5SXin Li 
BlobOutputStreamBuffer(Blob * blob)220*7ba4dab5SXin Li BlobOutputStreamBuffer::BlobOutputStreamBuffer(Blob* blob)
221*7ba4dab5SXin Li     : OutputStreamBuffer(blob->data(), blob->size()), blob_(blob) {}
222*7ba4dab5SXin Li 
Advance()223*7ba4dab5SXin Li bool BlobOutputStreamBuffer::Advance() {
224*7ba4dab5SXin Li   ptrdiff_t offset = pos_ - blob_->data();
225*7ba4dab5SXin Li   if (!blob_->Resize(max<size_t>(blob_->size() * 2, 32))) {
226*7ba4dab5SXin Li     return false;
227*7ba4dab5SXin Li   }
228*7ba4dab5SXin Li   pos_ = blob_->data() + offset;
229*7ba4dab5SXin Li   end_ = blob_->data() + blob_->size();
230*7ba4dab5SXin Li   return true;
231*7ba4dab5SXin Li }
232*7ba4dab5SXin Li 
Truncate()233*7ba4dab5SXin Li bool BlobOutputStreamBuffer::Truncate() {
234*7ba4dab5SXin Li   if (!blob_->Resize(pos_ - blob_->data())) {
235*7ba4dab5SXin Li     return false;
236*7ba4dab5SXin Li   }
237*7ba4dab5SXin Li   end_ = blob_->data() + blob_->size();
238*7ba4dab5SXin Li   pos_ = end_;
239*7ba4dab5SXin Li   return true;
240*7ba4dab5SXin Li }
241*7ba4dab5SXin Li 
ProtoReader(InputStreamBuffer * stream_buffer)242*7ba4dab5SXin Li ProtoReader::ProtoReader(InputStreamBuffer* stream_buffer)
243*7ba4dab5SXin Li     : stream_buffer_(stream_buffer) {}
244*7ba4dab5SXin Li 
ReadWireTag()245*7ba4dab5SXin Li bool ProtoReader::ReadWireTag() {
246*7ba4dab5SXin Li   uint64_t wire_tag;
247*7ba4dab5SXin Li   if (!DecodeVarint(stream_buffer_, &wire_tag)) {
248*7ba4dab5SXin Li     return false;
249*7ba4dab5SXin Li   }
250*7ba4dab5SXin Li 
251*7ba4dab5SXin Li   wire_type_ = wire_tag & 0x7;
252*7ba4dab5SXin Li   field_number_ = wire_tag >> 3;
253*7ba4dab5SXin Li   switch (wire_type()) {
254*7ba4dab5SXin Li     case WireType::kLengthDelimited: {
255*7ba4dab5SXin Li       uint64_t size;
256*7ba4dab5SXin Li       if (!DecodeVarint(stream_buffer_, &size)) {
257*7ba4dab5SXin Li         return false;
258*7ba4dab5SXin Li       }
259*7ba4dab5SXin Li       field_size_ = static_cast<size_t>(size);
260*7ba4dab5SXin Li       if (static_cast<uint64_t>(field_size_) != size) {
261*7ba4dab5SXin Li         return false;
262*7ba4dab5SXin Li       }
263*7ba4dab5SXin Li       break;
264*7ba4dab5SXin Li     }
265*7ba4dab5SXin Li     case WireType::kFixed64:
266*7ba4dab5SXin Li       field_size_ = sizeof(uint64_t);
267*7ba4dab5SXin Li       break;
268*7ba4dab5SXin Li     case WireType::kFixed32:
269*7ba4dab5SXin Li       field_size_ = sizeof(uint32_t);
270*7ba4dab5SXin Li       break;
271*7ba4dab5SXin Li     case WireType::kVarint:
272*7ba4dab5SXin Li     case WireType::kStartGroup:
273*7ba4dab5SXin Li     case WireType::kEndGroup:
274*7ba4dab5SXin Li       field_size_ = 0;
275*7ba4dab5SXin Li       break;
276*7ba4dab5SXin Li   }
277*7ba4dab5SXin Li 
278*7ba4dab5SXin Li   return true;
279*7ba4dab5SXin Li }
280*7ba4dab5SXin Li 
ReadVarint(uint64_t * value)281*7ba4dab5SXin Li bool ProtoReader::ReadVarint(uint64_t* value) {
282*7ba4dab5SXin Li   NVRAM_CHECK(wire_type() == WireType::kVarint);
283*7ba4dab5SXin Li   return DecodeVarint(stream_buffer_, value);
284*7ba4dab5SXin Li }
285*7ba4dab5SXin Li 
ReadLengthDelimited(void * data,size_t size)286*7ba4dab5SXin Li bool ProtoReader::ReadLengthDelimited(void* data, size_t size) {
287*7ba4dab5SXin Li   NVRAM_CHECK(wire_type() == WireType::kLengthDelimited);
288*7ba4dab5SXin Li   return stream_buffer_->Read(data, size);
289*7ba4dab5SXin Li }
290*7ba4dab5SXin Li 
SkipField()291*7ba4dab5SXin Li bool ProtoReader::SkipField() {
292*7ba4dab5SXin Li   if (wire_type() == WireType::kVarint) {
293*7ba4dab5SXin Li     uint64_t dummy;
294*7ba4dab5SXin Li     return DecodeVarint(stream_buffer_, &dummy);
295*7ba4dab5SXin Li   } else if (field_size_ > 0) {
296*7ba4dab5SXin Li     return stream_buffer_->Skip(field_size_);
297*7ba4dab5SXin Li   }
298*7ba4dab5SXin Li 
299*7ba4dab5SXin Li   return true;
300*7ba4dab5SXin Li }
301*7ba4dab5SXin Li 
ProtoWriter(OutputStreamBuffer * stream_buffer)302*7ba4dab5SXin Li ProtoWriter::ProtoWriter(OutputStreamBuffer* stream_buffer)
303*7ba4dab5SXin Li     : stream_buffer_(stream_buffer) {}
304*7ba4dab5SXin Li 
WriteVarint(uint64_t value)305*7ba4dab5SXin Li bool ProtoWriter::WriteVarint(uint64_t value) {
306*7ba4dab5SXin Li   return WriteWireTag(WireType::kVarint) &&
307*7ba4dab5SXin Li          EncodeVarint(stream_buffer_, value);
308*7ba4dab5SXin Li }
309*7ba4dab5SXin Li 
WriteLengthDelimited(const void * data,size_t size)310*7ba4dab5SXin Li bool ProtoWriter::WriteLengthDelimited(const void* data, size_t size) {
311*7ba4dab5SXin Li   return WriteWireTag(WireType::kLengthDelimited) &&
312*7ba4dab5SXin Li          EncodeVarint(stream_buffer_, size) &&
313*7ba4dab5SXin Li          stream_buffer_->Write(data, size);
314*7ba4dab5SXin Li }
315*7ba4dab5SXin Li 
WriteLengthHeader(size_t size)316*7ba4dab5SXin Li bool ProtoWriter::WriteLengthHeader(size_t size) {
317*7ba4dab5SXin Li   return WriteWireTag(WireType::kLengthDelimited) &&
318*7ba4dab5SXin Li          EncodeVarint(stream_buffer_, size);
319*7ba4dab5SXin Li }
320*7ba4dab5SXin Li 
WriteWireTag(WireType wire_type)321*7ba4dab5SXin Li bool ProtoWriter::WriteWireTag(WireType wire_type) {
322*7ba4dab5SXin Li   return EncodeVarint(stream_buffer_,
323*7ba4dab5SXin Li                       (field_number_ << 3) | static_cast<uint64_t>(wire_type));
324*7ba4dab5SXin Li }
325*7ba4dab5SXin Li 
326*7ba4dab5SXin Li }  // namespace nvram
327