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