blob: ac03e0944bd620528261703af8503d5d4dfae964 [file] [log] [blame]
/*
* Copyright (C) 2016 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.
*/
#ifndef NVRAM_CORE_NVRAM_MANAGER_H_
#define NVRAM_CORE_NVRAM_MANAGER_H_
#include <nvram/messages/nvram_messages.h>
#include <nvram/core/persistence.h>
namespace nvram {
// |NvramManager| implements the core functionality of the access-controlled
// NVRAM HAL backend. It keeps track of the allocated spaces and their state,
// including the transient state that is held per boot. It provides operations
// for querying, creating, deleting, reading and writing spaces. It deals with
// persistent storage objects in the form of |NvramHeader| and |NvramSpace|
// objects and uses the persistence layer to read and write them from persistent
// storage.
class NvramManager {
public:
// Looks at |request| to determine the command to execute, extracts the
// request parameters and invokes the correct handler function. Stores status
// and output parameters in |response|.
void Dispatch(const Request& request, Response* response);
nvram_result_t GetInfo(const GetInfoRequest& request,
GetInfoResponse* response);
nvram_result_t CreateSpace(const CreateSpaceRequest& request,
CreateSpaceResponse* response);
nvram_result_t GetSpaceInfo(const GetSpaceInfoRequest& request,
GetSpaceInfoResponse* response);
nvram_result_t DeleteSpace(const DeleteSpaceRequest& request,
DeleteSpaceResponse* response);
nvram_result_t DisableCreate(const DisableCreateRequest& request,
DisableCreateResponse* response);
nvram_result_t WriteSpace(const WriteSpaceRequest& request,
WriteSpaceResponse* response);
nvram_result_t ReadSpace(const ReadSpaceRequest& request,
ReadSpaceResponse* response);
nvram_result_t LockSpaceWrite(const LockSpaceWriteRequest& request,
LockSpaceWriteResponse* response);
nvram_result_t LockSpaceRead(const LockSpaceReadRequest& request,
LockSpaceReadResponse* response);
// The wipe functions are meant for use by firmware after determining the
// device's mode of operation. These can be used to clear access-controlled
// NVRAM when a user invokes a full hardware reset. Note that in regular
// operation, the user *MUST BE PREVENTED* from wiping access-controlled
// NVRAM.
//
// If a full hardware reset can conveniently clear the access-controlled NVRAM
// storage area out of band, it's fine to do so. In this case, the
// wiping-related commands should not be exposed at all. Note that this is the
// default behavior - the reference implementation will ignore all wipe
// requests unless compiled with NVRAM_WIPE_STORAGE_SUPPORT=1.
//
// For devices where firmware doesn't have direct control over the storage
// area used by access-controlled NVRAM, the wiping commands are provided to
// facilitate clearing storage:
// 1. Determine boot mode.
// 2. If not in recovery mode, call DisableWipe(). All further wipe requests
// will be rejected. A reboot (or TEE restart for that matter) is
// required before a new decision can be made.
// 3. If operating in recovery mode, forgo calling DisableWipe(). The
// recovery process will then be able to invoke WipeStorage() later as
// needed.
nvram_result_t WipeStorage(const WipeStorageRequest& request,
WipeStorageResponse* response);
nvram_result_t DisableWipe(const DisableWipeRequest& request,
DisableWipeResponse* response);
private:
// Holds transient state corresponding to an allocated NVRAM space, i.e. meta
// data valid for a single boot. One instance of this struct is kept in memory
// in the |spaces_| array for each of the spaces that are currently allocated.
struct SpaceListEntry {
uint32_t index;
bool write_locked = false;
bool read_locked = false;
};
// |SpaceRecord| holds all information known about a space. It includes both
// an index and pointer to the transient information held in the
// |SpaceListEntry| in the |spaces_| array and the persistent |NvramSpace|
// state held in permanent storage. We only load the persistent space data
// from storage when it is needed for an operation, such as reading and
// writing space contents.
struct SpaceRecord {
// Access control check for write access to the space. The
// |authorization_value| is only relevant if the space was configured to
// require authorization. Returns RESULT_SUCCESS if write access is
// permitted and a suitable result code to return to the client on failure.
nvram_result_t CheckWriteAccess(const Blob& authorization_value);
// Access control check for read access to the space. The
// |authorization_value| is only relevant if the space was configured to
// require authorization. Returns RESULT_SUCCESS if write access is
// permitted and a suitable result code to return the client on failure.
nvram_result_t CheckReadAccess(const Blob& authorization_value);
size_t array_index = 0;
SpaceListEntry* transient = nullptr;
NvramSpace persistent;
};
// Initializes |header_| from storage if that hasn't happened already. Returns
// true if NvramManager object is initialized and ready to serve requests. May
// be called again after failure to attempt initialization again.
bool Initialize();
// Finds the array index in |spaces_| that corresponds to |space_index|.
// Returns |kMaxSpaces| if there is no matching space.
size_t FindSpace(uint32_t space_index);
// Loads space data for |index|. Fills in |space_record| and returns true if
// successful. Returns false and sets |result| on error.
bool LoadSpaceRecord(uint32_t index,
SpaceRecord* space_record,
nvram_result_t* result);
// Writes the header to storage and returns a suitable status code.
nvram_result_t WriteHeader(Optional<uint32_t> provisional_index);
// Write |space| data for |index|.
nvram_result_t WriteSpace(uint32_t index, const NvramSpace& space);
// Maximum number of NVRAM spaces we're willing to allocate.
static constexpr size_t kMaxSpaces = 32;
bool initialized_ = false;
bool disable_create_ = false;
bool disable_wipe_ = false;
// Bookkeeping information for allocated spaces.
size_t num_spaces_ = 0;
SpaceListEntry spaces_[kMaxSpaces];
};
} // namespace nvram
#endif // NVRAM_CORE_NVRAM_MANAGER_H_