18748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler/* 28748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler * Copyright (C) 2016 The Android Open Source Project 38748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler * 48748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler * Licensed under the Apache License, Version 2.0 (the "License"); 58748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler * you may not use this file except in compliance with the License. 68748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler * You may obtain a copy of the License at 78748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler * 88748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler * http://www.apache.org/licenses/LICENSE-2.0 98748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler * 108748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler * Unless required by applicable law or agreed to in writing, software 118748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler * distributed under the License is distributed on an "AS IS" BASIS, 128748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 138748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler * See the License for the specific language governing permissions and 148748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler * limitations under the License. 158748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler */ 168748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler 178748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler#include "nvram/core/persistence.h" 188748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler 198748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler#include <nvram/messages/io.h> 208748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler#include <nvram/messages/proto.hpp> 218748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler 228748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler#include <nvram/core/logger.h> 238748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler 248748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nisslernamespace nvram { 258748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler 268748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nisslernamespace { 278748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler 288748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler// Magic constants that identify encoded |NvramHeader| vs. |NvramSpace| objects. 298748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nisslerconst uint32_t kHeaderMagic = 0x4e5648; // "NVH" in hex 308748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nisslerconst uint32_t kSpaceMagic = 0x4e5653; // "NVS" in hex 318748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler 328748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler// Encodes an |object| as a protobuf message and writes it to |blob|. Note that 338748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler// standard protobuf encoding doesn't include information about the overall size 348748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler// of the encoded object. This is not good enough here, as encoding should 358748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler// gracefully handle trailing data on decode, e.g. to allow underlying storage 368748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler// systems that only provide block-granular I/O. 378748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler// 388748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler// Not that the code uses |proto::detail::MessageEncoder<Object>::Encode()| 398748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler// instead of the regular |proto::Encode()| to encode the message. This results 408748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler// in the message being wrapped in a length-delimited proto field record, so the 418748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler// length field can be used to determine the actual length of the message. Also, 428748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler// this gives us the opportunity to encode a magic constant in the field number 438748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler// bits of the wire tag, thus allowing us to detect situations where we're 448748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler// attempting to decode a message of wrong type. 458748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nisslertemplate <uint32_t magic, typename Object> 468748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nisslerstorage::Status EncodeObject(const Object& object, Blob* blob) { 478748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler BlobOutputStreamBuffer stream(blob); 488748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler ProtoWriter writer(&stream); 498748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler writer.set_field_number(magic); 508748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler if (!proto::detail::MessageEncoder<Object>::Encode(object, &writer) || 518748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler !stream.Truncate()) { 528748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler NVRAM_LOG_ERR("Failed to encode object."); 538748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler return storage::Status::kStorageError; 548748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler } 558748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler return storage::Status::kSuccess; 568748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler} 578748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler 588748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler// Decodes a protobuf-encoded |object| from |blob|. It is OK if the provided 598748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler// |blob| includes trailing data that doesn't belong to the encoded object. 608748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler// 618748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler// Note that the code below reads the wire tag to strip the wrapping proto field 628748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler// record produced by |EncodeObject|. It then checks the magic field number to 638748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler// make sure we're decoding a message of correct type. Finally, 648748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler// |proto::detail::MessageDecoder<Object>::Decode()| takes care of reading the 658748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler// message payload from the proto field record. 668748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nisslertemplate <uint32_t magic, typename Object> 678748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nisslerstorage::Status DecodeObject(const Blob& blob, Object* object) { 688748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler InputStreamBuffer stream(blob.data(), blob.size()); 698748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler ProtoReader reader(&stream); 708748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler if (!reader.ReadWireTag() || reader.field_number() != magic || 718748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler reader.wire_type() != WireType::kLengthDelimited || 728748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler !proto::detail::MessageDecoder<Object>::Decode(*object, &reader)) { 738748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler NVRAM_LOG_ERR("Failed to decode object of size %zu.", blob.size()); 748748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler return storage::Status::kStorageError; 758748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler } 768748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler return storage::Status::kSuccess; 778748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler} 788748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler 798748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler} // namespace 808748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler 818748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nisslertemplate <> struct DescriptorForType<NvramHeader> { 828748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler static constexpr auto kFields = 838748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler MakeFieldList(MakeField(1, &NvramHeader::version), 848748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler MakeField(2, &NvramHeader::flags), 858748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler MakeField(3, &NvramHeader::allocated_indices), 868748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler MakeField(4, &NvramHeader::provisional_index)); 878748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler}; 888748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler 898748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nisslertemplate <> struct DescriptorForType<NvramSpace> { 908748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler static constexpr auto kFields = 918748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler MakeFieldList(MakeField(1, &NvramSpace::flags), 928748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler MakeField(2, &NvramSpace::controls), 938748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler MakeField(3, &NvramSpace::authorization_value), 948748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler MakeField(4, &NvramSpace::contents)); 958748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler}; 968748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler 978748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nisslernamespace persistence { 988748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler 998748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nisslerstorage::Status LoadHeader(NvramHeader* header) { 1008748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler Blob blob; 1018748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler storage::Status status = storage::LoadHeader(&blob); 1028748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler if (status != storage::Status::kSuccess) { 1038748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler return status; 1048748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler } 1058748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler return DecodeObject<kHeaderMagic>(blob, header); 1068748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler} 1078748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler 1088748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nisslerstorage::Status StoreHeader(const NvramHeader& header) { 1098748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler Blob blob; 1108748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler storage::Status status = EncodeObject<kHeaderMagic>(header, &blob); 1118748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler if (status != storage::Status::kSuccess) { 1128748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler return status; 1138748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler } 1148748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler return storage::StoreHeader(blob); 1158748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler} 1168748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler 1178748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nisslerstorage::Status LoadSpace(uint32_t index, NvramSpace* space) { 1188748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler Blob blob; 1198748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler storage::Status status = storage::LoadSpace(index, &blob); 1208748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler if (status != storage::Status::kSuccess) { 1218748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler return status; 1228748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler } 1238748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler return DecodeObject<kSpaceMagic>(blob, space); 1248748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler} 1258748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler 1268748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nisslerstorage::Status StoreSpace(uint32_t index, const NvramSpace& space) { 1278748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler Blob blob; 1288748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler storage::Status status = EncodeObject<kSpaceMagic>(space, &blob); 1298748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler if (status != storage::Status::kSuccess) { 1308748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler return status; 1318748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler } 1328748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler return storage::StoreSpace(index, blob); 1338748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler} 1348748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler 1358748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nisslerstorage::Status DeleteSpace(uint32_t index) { 1368748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler return storage::DeleteSpace(index); 1378748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler} 1388748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler 1398748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler} // namespace persistence 1408748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler} // namespace nvram 141