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