1 /* 2 * Copyright (c) 2013-2020 ARM Limited. All rights reserved. 3 * 4 * SPDX-License-Identifier: Apache-2.0 5 * 6 * Licensed under the Apache License, Version 2.0 (the License); you may 7 * not use this file except in compliance with the License. 8 * You may obtain a copy of the License at 9 * 10 * www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an AS IS BASIS, WITHOUT 14 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 * 18 * $Date: 24. January 2020 19 * $Revision: V1.2 20 * 21 * Project: Storage Driver definitions 22 */ 23 24 /* History: 25 * Version 1.2 26 * Removed volatile from ARM_STORAGE_STATUS 27 * Version 1.1 28 * ARM_STORAGE_STATUS made volatile 29 * Version 1.00 30 * Initial release 31 */ 32 33 #ifndef DRIVER_STORAGE_H_ 34 #define DRIVER_STORAGE_H_ 35 36 #ifdef __cplusplus 37 extern "C" { 38 #endif 39 40 #include "Driver_Common.h" 41 42 #define ARM_STORAGE_API_VERSION ARM_DRIVER_VERSION_MAJOR_MINOR(1,2) /* API version */ 43 44 45 #define _ARM_Driver_Storage_(n) Driver_Storage##n 46 #define ARM_Driver_Storage_(n) _ARM_Driver_Storage_(n) 47 48 #define ARM_STORAGE_INVALID_OFFSET (0xFFFFFFFFFFFFFFFFULL) ///< Invalid address (relative to a storage controller's 49 /// address space). A storage block may never start at this address. 50 51 #define ARM_STORAGE_INVALID_ADDRESS (0xFFFFFFFFUL) ///< Invalid address within the processor's memory address space. 52 /// Refer to memory-mapped storage, i.e. \ref ARM_DRIVER_STORAGE::ResolveAddress(). 53 54 /****** Storage specific error codes *****/ 55 #define ARM_STORAGE_ERROR_NOT_ERASABLE (ARM_DRIVER_ERROR_SPECIFIC - 1) ///< Part (or all) of the range provided to Erase() isn't erasable. 56 #define ARM_STORAGE_ERROR_NOT_PROGRAMMABLE (ARM_DRIVER_ERROR_SPECIFIC - 2) ///< Part (or all) of the range provided to ProgramData() isn't programmable. 57 #define ARM_STORAGE_ERROR_PROTECTED (ARM_DRIVER_ERROR_SPECIFIC - 3) ///< Part (or all) of the range to Erase() or ProgramData() is protected. 58 59 /** 60 * \brief Attributes of the storage range within a storage block. 61 */ 62 typedef struct _ARM_STORAGE_BLOCK_ATTRIBUTES { 63 uint32_t erasable : 1; ///< Erasing blocks is permitted with a minimum granularity of 'erase_unit'. 64 /// @note if 'erasable' is 0 (i.e. the 'erase' operation isn't available) then 65 /// 'erase_unit' (see below) is immaterial and should be 0. 66 uint32_t programmable : 1; ///< Writing to ranges is permitted with a minimum granularity of 'program_unit'. 67 /// Writes are typically achieved through the ProgramData operation (following an erase); 68 /// if storage isn't erasable (see 'erasable' above) but is memory-mapped 69 /// (i.e. 'memory_mapped'), it can be written directly using memory-store operations. 70 uint32_t executable : 1; ///< This storage block can hold program data; the processor can fetch and execute code 71 /// sourced from it. Often this is accompanied with the device being 'memory_mapped' (see \ref ARM_STORAGE_INFO). 72 uint32_t protectable : 1; ///< The entire block can be protected from program and erase operations. Once protection 73 /// is enabled for a block, its 'erasable' and 'programmable' bits are turned off. 74 uint32_t reserved : 28; 75 uint32_t erase_unit; ///< Minimum erase size in bytes. 76 /// The offset of the start of the erase-range should also be aligned with this value. 77 /// Applicable if the 'erasable' attribute is set for the block. 78 /// @note if 'erasable' (see above) is 0 (i.e. the 'erase' operation isn't available) then 79 /// 'erase_unit' is immaterial and should be 0. 80 uint32_t protection_unit; ///< Minimum protectable size in bytes. Applicable if the 'protectable' 81 /// attribute is set for the block. This should be a divisor of the block's size. A 82 /// block can be considered to be made up of consecutive, individually-protectable fragments. 83 } ARM_STORAGE_BLOCK_ATTRIBUTES; 84 85 /** 86 * \brief A storage block is a range of memory with uniform attributes. 87 */ 88 typedef struct _ARM_STORAGE_BLOCK { 89 uint64_t addr; ///< This is the start address of the storage block. It is 90 /// expressed as an offset from the start of the storage map 91 /// maintained by the owning storage controller. 92 uint64_t size; ///< This is the size of the storage block, in units of bytes. 93 /// Together with addr, it describes a range [addr, addr+size). 94 ARM_STORAGE_BLOCK_ATTRIBUTES attributes; ///< Attributes for this block. 95 } ARM_STORAGE_BLOCK; 96 97 /** 98 * The check for a valid ARM_STORAGE_BLOCK. 99 */ 100 #define ARM_STORAGE_VALID_BLOCK(BLK) (((BLK)->addr != ARM_STORAGE_INVALID_OFFSET) && ((BLK)->size != 0)) 101 102 /** 103 * \brief Values for encoding storage memory-types with respect to programmability. 104 * 105 * Please ensure that the maximum of the following memory types doesn't exceed 16; we 106 * encode this in a 4-bit field within ARM_STORAGE_INFO::programmability. 107 */ 108 #define ARM_STORAGE_PROGRAMMABILITY_RAM (0U) 109 #define ARM_STORAGE_PROGRAMMABILITY_ROM (1U) ///< Read-only memory. 110 #define ARM_STORAGE_PROGRAMMABILITY_WORM (2U) ///< write-once-read-only-memory (WORM). 111 #define ARM_STORAGE_PROGRAMMABILITY_ERASABLE (3U) ///< re-programmable based on erase. Supports multiple writes. 112 113 /** 114 * Values for encoding data-retention levels for storage blocks. 115 * 116 * Please ensure that the maximum of the following retention types doesn't exceed 16; we 117 * encode this in a 4-bit field within ARM_STORAGE_INFO::retention_level. 118 */ 119 #define ARM_RETENTION_WHILE_DEVICE_ACTIVE (0U) ///< Data is retained only during device activity. 120 #define ARM_RETENTION_ACROSS_SLEEP (1U) ///< Data is retained across processor sleep. 121 #define ARM_RETENTION_ACROSS_DEEP_SLEEP (2U) ///< Data is retained across processor deep-sleep. 122 #define ARM_RETENTION_BATTERY_BACKED (3U) ///< Data is battery-backed. Device can be powered off. 123 #define ARM_RETENTION_NVM (4U) ///< Data is retained in non-volatile memory. 124 125 /** 126 * Device Data Security Protection Features. Applicable mostly to EXTERNAL_NVM. 127 */ 128 typedef struct _ARM_STORAGE_SECURITY_FEATURES { 129 uint32_t acls : 1; ///< Protection against internal software attacks using ACLs. 130 uint32_t rollback_protection : 1; ///< Roll-back protection. Set to true if the creator of the storage 131 /// can ensure that an external attacker can't force an 132 /// older firmware to run or to revert back to a previous state. 133 uint32_t tamper_proof : 1; ///< Tamper-proof memory (will be deleted on tamper-attempts using board level or chip level sensors). 134 uint32_t internal_flash : 1; ///< Internal flash. 135 uint32_t reserved1 : 12; 136 137 /** 138 * Encode support for hardening against various classes of attacks. 139 */ 140 uint32_t software_attacks : 1; ///< device software (malware running on the device). 141 uint32_t board_level_attacks : 1; ///< board level attacks (debug probes, copy protection fuses.) 142 uint32_t chip_level_attacks : 1; ///< chip level attacks (tamper-protection). 143 uint32_t side_channel_attacks : 1; ///< side channel attacks. 144 uint32_t reserved2 : 12; 145 } ARM_STORAGE_SECURITY_FEATURES; 146 147 #define ARM_STORAGE_PROGRAM_CYCLES_INFINITE (0UL) /**< Infinite or unknown endurance for reprogramming. */ 148 149 /** 150 * Device level metadata regarding the Storage implementation. 151 */ 152 typedef struct _ARM_STORAGE_INFO { 153 uint64_t total_storage; ///< Total available storage, in bytes. 154 uint32_t program_unit; ///< Minimum programming size in bytes. 155 /// The offset of the start of the program-range should also be aligned with this value. 156 /// Applicable only if the 'programmable' attribute is set for a block. 157 /// @note setting program_unit to 0 has the effect of disabling the size and alignment 158 /// restrictions (setting it to 1 also has the same effect). 159 uint32_t optimal_program_unit; ///< Optimal programming page-size in bytes. Some storage controllers 160 /// have internal buffers into which to receive data. Writing in chunks of 161 /// 'optimal_program_unit' would achieve maximum programming speed. 162 /// Applicable only if the 'programmable' attribute is set for the underlying block(s). 163 uint32_t program_cycles; ///< A measure of endurance for reprogramming. 164 /// Use ARM_STORAGE_PROGRAM_CYCLES_INFINITE for infinite or unknown endurance. 165 uint32_t erased_value : 1; ///< Contents of erased memory (usually 1 to indicate erased bytes with state 0xFF). 166 uint32_t memory_mapped : 1; ///< This storage device has a mapping onto the processor's memory address space. 167 /// @note For a memory-mapped block which isn't erasable but is programmable (i.e. if 168 /// 'erasable' is set to 0, but 'programmable' is 1), writes should be possible directly to 169 /// the memory-mapped storage without going through the ProgramData operation. 170 uint32_t programmability : 4; ///< A value to indicate storage programmability. 171 uint32_t retention_level : 4; 172 uint32_t reserved : 22; 173 ARM_STORAGE_SECURITY_FEATURES security; ///< \ref ARM_STORAGE_SECURITY_FEATURES 174 } ARM_STORAGE_INFO; 175 176 /** 177 \brief Operating status of the storage controller. 178 */ 179 typedef struct _ARM_STORAGE_STATUS { 180 uint32_t busy : 1; ///< Controller busy flag 181 uint32_t error : 1; ///< Read/Program/Erase error flag (cleared on start of next operation) 182 uint32_t reserved : 30; 183 } ARM_STORAGE_STATUS; 184 185 /** 186 * \brief Storage Driver API Capabilities. 187 */ 188 typedef struct _ARM_STORAGE_CAPABILITIES { 189 uint32_t asynchronous_ops : 1; ///< Used to indicate if APIs like initialize, 190 /// read, erase, program, etc. can operate in asynchronous mode. 191 /// Setting this bit to 1 means that the driver is capable 192 /// of launching asynchronous operations; command completion is 193 /// signaled by the invocation of a completion callback. If 194 /// set to 1, drivers may still complete asynchronous 195 /// operations synchronously as necessary (in which case they 196 /// return a positive error code to indicate synchronous completion). 197 uint32_t erase_all : 1; ///< Supports EraseAll operation. 198 uint32_t reserved : 30; ///< Reserved (must be zero) 199 } ARM_STORAGE_CAPABILITIES; 200 201 /** 202 * Command opcodes for Storage. 203 */ 204 typedef enum _ARM_STORAGE_OPERATION { 205 ARM_STORAGE_OPERATION_GET_VERSION, 206 ARM_STORAGE_OPERATION_GET_CAPABILITIES, 207 ARM_STORAGE_OPERATION_INITIALIZE, 208 ARM_STORAGE_OPERATION_UNINITIALIZE, 209 ARM_STORAGE_OPERATION_POWER_CONTROL, 210 ARM_STORAGE_OPERATION_READ_DATA, 211 ARM_STORAGE_OPERATION_PROGRAM_DATA, 212 ARM_STORAGE_OPERATION_ERASE, 213 ARM_STORAGE_OPERATION_ERASE_ALL, 214 ARM_STORAGE_OPERATION_GET_STATUS, 215 ARM_STORAGE_OPERATION_GET_INFO, 216 ARM_STORAGE_OPERATION_RESOLVE_ADDRESS, 217 ARM_STORAGE_OPERATION_GET_NEXT_BLOCK, 218 ARM_STORAGE_OPERATION_GET_BLOCK 219 } ARM_STORAGE_OPERATION; 220 221 // Function documentation 222 /** 223 \fn ARM_DRIVER_VERSION ARM_Storage_GetVersion (void) 224 \brief Get driver version. 225 \return \ref ARM_DRIVER_VERSION 226 */ 227 /** 228 \fn ARM_STORAGE_CAPABILITIES ARM_Storage_GetCapabilities (void) 229 \brief Get driver capabilities. 230 \return \ref ARM_STORAGE_CAPABILITIES 231 */ 232 /** 233 \fn int32_t ARM_Storage_Initialize (ARM_Storage_Callback_t callback) 234 \brief Initialize the Storage interface. 235 \param [in] callback Pointer to \ref ARM_Storage_Callback_t. 236 Caller-defined callback to be invoked upon command completion 237 for asynchronous APIs (including the completion of 238 initialization). Use a NULL pointer when no callback 239 signals are required. 240 \return If asynchronous activity is launched, invocation 241 ARM_DRIVER_OK, and the caller can expect to receive a callback in the 242 future with a status value of ARM_DRIVER_OK or an error-code. In the 243 case of synchronous execution, control returns after completion with a 244 value of 1. Return values less than ARM_DRIVER_OK (0) signify errors. 245 */ 246 /** 247 \fn int32_t ARM_Storage_Uninitialize (void) 248 \brief De-initialize the Storage Interface. 249 \return If asynchronous activity is launched, an invocation returns 250 ARM_DRIVER_OK, and the caller can expect to receive a callback in the 251 future with a status value of ARM_DRIVER_OK or an error-code. In the 252 case of synchronous execution, control returns after completion with a 253 value of 1. Return values less than ARM_DRIVER_OK (0) signify errors. 254 */ 255 /** 256 \fn int32_t ARM_Storage_PowerControl (ARM_POWER_STATE state) 257 \brief Control the Storage interface power. 258 \param[in] state Power state 259 \return If asynchronous activity is launched, an invocation returns 260 ARM_DRIVER_OK, and the caller can expect to receive a callback in the 261 future with a status value of ARM_DRIVER_OK or an error-code. In the 262 case of synchronous execution, control returns after completion with a 263 value of 1. Return values less than ARM_DRIVER_OK (0) signify errors. 264 */ 265 /** 266 \fn int32_t ARM_Storage_ReadData (uint64_t addr, void *data, uint32_t size) 267 \brief Read data from Storage. 268 \param[in] addr Data address. 269 \param[out] data Pointer to a buffer storing the data read from Storage. 270 \param[in] size Number of bytes to read. The data buffer 271 should be at least as large as this size. 272 \return If asynchronous activity is launched, an invocation returns 273 ARM_DRIVER_OK, and the caller can expect to receive a callback in the 274 future with the number of successfully transferred bytes passed in as 275 the 'status' parameter. In the case of synchronous execution, control 276 returns after completion with a positive transfer-count. Return values 277 less than ARM_DRIVER_OK (0) signify errors. 278 */ 279 /** 280 \fn int32_t ARM_Storage_ProgramData (uint64_t addr, const void *data, uint32_t size) 281 \brief Program data to Storage. 282 \param [in] addr This is the start address of the range to be written into. It 283 needs to be aligned to the device's \em program_unit 284 specified in \ref ARM_STORAGE_INFO. 285 \param [in] data The source of the write operation. The buffer is owned by the 286 caller and should remain accessible for the lifetime of this 287 command. 288 \param [in] size The number of bytes requested to be written. The buffer 289 should be at least as large as this size. \note 'size' should 290 be a multiple of the device's 'program_unit' (see \ref 291 ARM_STORAGE_INFO). 292 \return If asynchronous activity is launched, an invocation returns 293 ARM_DRIVER_OK, and the caller can expect to receive a callback in the 294 future with the number of successfully transferred bytes passed in as 295 the 'status' parameter. In the case of synchronous execution, control 296 returns after completion with a positive transfer-count. Return values 297 less than ARM_DRIVER_OK (0) signify errors. 298 */ 299 /** 300 \fn int32_t ARM_Storage_Erase (uint64_t addr, uint32_t size) 301 \brief Erase Storage range. 302 \param [in] addr This is the start-address of the range to be erased. It must 303 start at an 'erase_unit' boundary of the underlying block. 304 \param [in] size Size (in bytes) of the range to be erased. 'addr + size' 305 must be aligned with the 'erase_unit' of the underlying 306 block. 307 \return If the range to be erased doesn't align with the erase_units of the 308 respective start and end blocks, ARM_DRIVER_ERROR_PARAMETER is 309 returned. If any part of the range is protected, 310 ARM_STORAGE_ERROR_PROTECTED is returned. If any part of the range 311 is not erasable, ARM_STORAGE_ERROR_NOT_ERASABLE is returned. All 312 such sanity-check failures result in the error code being 313 returned synchronously and the storage bytes within the range 314 remain unaffected. Otherwise the function executes in the 315 following ways: If asynchronous activity is launched, an 316 invocation returns ARM_DRIVER_OK, and the caller can expect to 317 receive a callback in the future with the number of successfully 318 erased bytes passed in as the 'status' parameter. In the case of 319 synchronous execution, control returns after completion with a 320 positive erase-count. Return values less than ARM_DRIVER_OK (0) 321 signify errors. 322 */ 323 /** 324 \fn int32_t ARM_Storage_EraseAll (void) 325 \brief Erase complete Storage. 326 \return If any part of the storage range is protected, 327 ARM_STORAGE_ERROR_PROTECTED is returned. If any part of the 328 storage range is not erasable, ARM_STORAGE_ERROR_NOT_ERASABLE is 329 returned. All such sanity-check failures result in the error code 330 being returned synchronously and the storage bytes within the 331 range remain unaffected. Otherwise the function executes in the 332 following ways: If asynchronous activity is launched, an 333 invocation returns ARM_DRIVER_OK, and the caller can expect to 334 receive a callback in the future with ARM_DRIVER_OK passed in as 335 the 'status' parameter. In the case of synchronous execution, 336 control returns after completion with a value of 1. Return values 337 less than ARM_DRIVER_OK (0) signify errors. 338 */ 339 /** 340 \fn ARM_STORAGE_STATUS ARM_Storage_GetStatus (void) 341 \brief Get Storage status. 342 \return Storage status \ref ARM_STORAGE_STATUS 343 */ 344 /** 345 \fn int32_t ARM_Storage_GetInfo (ARM_STORAGE_INFO *info) 346 \brief Get Storage information. 347 \param[out] info A caller-supplied buffer capable of being filled in with an \ref ARM_STORAGE_INFO. 348 \return ARM_DRIVER_OK if a ARM_STORAGE_INFO structure containing top level 349 metadata about the storage controller is filled into the supplied 350 buffer, else an appropriate error value. 351 */ 352 /** 353 \fn uint32_t ARM_Storage_ResolveAddress(uint64_t addr) 354 \brief Resolve an address relative to the storage controller into a memory address. 355 \param[in] addr The address for which we want a resolution to the processor's physical address space. It is an offset from the 356 start of the storage map maintained by the owning storage 357 controller. 358 \return The resolved address in the processor's address space, else ARM_STORAGE_INVALID_ADDRESS. 359 */ 360 /** 361 \fn int32_t ARM_Storage_GetNextBlock(const ARM_STORAGE_BLOCK* prev_block, ARM_STORAGE_BLOCK *next_block); 362 \brief Advance to the successor of the current block (iterator). 363 \param[in] prev_block An existing block (iterator) within the same storage 364 controller. The memory buffer holding this block is owned 365 by the caller. This pointer may be NULL; if so, the 366 invocation fills in the first block into the out parameter: 367 'next_block'. 368 \param[out] next_block A caller-owned buffer large enough to be filled in with 369 the following ARM_STORAGE_BLOCK. It is legal to provide the 370 same buffer using 'next_block' as was passed in with 'prev_block'. It 371 is also legal to pass a NULL into this parameter if the 372 caller isn't interested in populating a buffer with the next 373 block, i.e. if the caller only wishes to establish the 374 presence of a next block. 375 \return ARM_DRIVER_OK if a valid next block is found (or first block, if 376 prev_block is passed as NULL); upon successful operation, the contents 377 of the next (or first) block are filled into the buffer pointed to by 378 the parameter 'next_block' and ARM_STORAGE_VALID_BLOCK(next_block) is 379 guaranteed to be true. Upon reaching the end of the sequence of blocks 380 (iterators), or in case the driver is unable to fetch information about 381 the next (or first) block, an error (negative) value is returned and an 382 invalid StorageBlock is populated into the supplied buffer. If 383 prev_block is NULL, the first block is returned. 384 */ 385 /** 386 \fn int32_t ARM_Storage_GetBlock(uint64_t addr, ARM_STORAGE_BLOCK *block); 387 \brief Find the storage block (iterator) encompassing a given storage address. 388 \param[in] addr Storage address in bytes. 389 \param[out] block A caller-owned buffer large enough to be filled in with the 390 ARM_STORAGE_BLOCK encapsulating the given address. This value 391 can also be passed in as NULL if the caller isn't interested 392 in populating a buffer with the block, if the caller only 393 wishes to establish the presence of a containing storage 394 block. 395 \return ARM_DRIVER_OK if a containing storage-block is found. In this case, 396 if block is non-NULL, the buffer pointed to by it is populated with 397 the contents of the storage block, i.e. if block is valid and a block is 398 found, ARM_STORAGE_VALID_BLOCK(block) would return true following this 399 call. If there is no storage block containing the given offset, or in 400 case the driver is unable to resolve an address to a storage-block, an 401 error (negative) value is returned and an invalid StorageBlock is 402 populated into the supplied buffer. 403 */ 404 405 /** 406 * Provides the typedef for the callback function \ref ARM_Storage_Callback_t. 407 */ 408 typedef void (*ARM_Storage_Callback_t)(int32_t status, ARM_STORAGE_OPERATION operation); 409 410 /** 411 * The set of operations constituting the Storage driver. 412 */ 413 typedef struct _ARM_DRIVER_STORAGE { 414 ARM_DRIVER_VERSION (*GetVersion) (void); ///< Pointer to \ref ARM_Storage_GetVersion : Get driver version. 415 ARM_STORAGE_CAPABILITIES (*GetCapabilities)(void); ///< Pointer to \ref ARM_Storage_GetCapabilities : Get driver capabilities. 416 int32_t (*Initialize) (ARM_Storage_Callback_t callback); ///< Pointer to \ref ARM_Storage_Initialize : Initialize the Storage Interface. 417 int32_t (*Uninitialize) (void); ///< Pointer to \ref ARM_Storage_Uninitialize : De-initialize the Storage Interface. 418 int32_t (*PowerControl) (ARM_POWER_STATE state); ///< Pointer to \ref ARM_Storage_PowerControl : Control the Storage interface power. 419 int32_t (*ReadData) (uint64_t addr, void *data, uint32_t size); ///< Pointer to \ref ARM_Storage_ReadData : Read data from Storage. 420 int32_t (*ProgramData) (uint64_t addr, const void *data, uint32_t size); ///< Pointer to \ref ARM_Storage_ProgramData : Program data to Storage. 421 int32_t (*Erase) (uint64_t addr, uint32_t size); ///< Pointer to \ref ARM_Storage_Erase : Erase Storage range. 422 int32_t (*EraseAll) (void); ///< Pointer to \ref ARM_Storage_EraseAll : Erase complete Storage. 423 ARM_STORAGE_STATUS (*GetStatus) (void); ///< Pointer to \ref ARM_Storage_GetStatus : Get Storage status. 424 int32_t (*GetInfo) (ARM_STORAGE_INFO *info); ///< Pointer to \ref ARM_Storage_GetInfo : Get Storage information. 425 uint32_t (*ResolveAddress) (uint64_t addr); ///< Pointer to \ref ARM_Storage_ResolveAddress : Resolve a storage address. 426 int32_t (*GetNextBlock) (const ARM_STORAGE_BLOCK* prev, ARM_STORAGE_BLOCK *next); ///< Pointer to \ref ARM_Storage_GetNextBlock : fetch successor for current block. 427 int32_t (*GetBlock) (uint64_t addr, ARM_STORAGE_BLOCK *block); ///< Pointer to \ref ARM_Storage_GetBlock : 428 } const ARM_DRIVER_STORAGE; 429 430 #ifdef __cplusplus 431 } 432 #endif 433 434 #endif /* DRIVER_STORAGE_H_ */ 435