MCCI Trusted Bootloader
Simple trusted bootloader and tools for small embedded systems
mcci_bootloader_platform_types.h
Go to the documentation of this file.
1/*
2
3Module: mcci_bootloader_platform_types.h
4
5Function:
6 Types for MCCI bootloader platform interface
7
8Copyright and License:
9 This file copyright (C) 2021 by
10
11 MCCI Corporation
12 3520 Krums Corners Road
13 Ithaca, NY 14850
14
15 See accompanying LICENSE file for copyright and license information.
16
17Author:
18 Terry Moore, MCCI Corporation March 2021
19
20*/
21
22#ifndef _mcci_bootloader_platform_types_h_
23#define _mcci_bootloader_platform_types_h_ /* prevent multiple includes */
24
25#pragma once
26
27#ifndef _mcci_bootloader_types_h_
29#endif
30
31#include <stdint.h>
32
34
35///
36/// \brief function type for platform intialization function
37///
38/// \details Functions of this type are called by the bootloader after
39/// RAM has been initialized. The function should set the system
40/// clock speed set up any "always needed" peripherals.
41///
43
44///
45/// \brief function type for preparing to launch an application
46///
47/// \details The bootloader calls this function just before jumping
48/// to the application. The function is required to return the
49/// platform to a reset-like state (making the bootloader
50/// maximally transparent).
51///
53
54///
55/// \brief function for reporting a fatal error
56///
57/// \param [in] errorCode failure reason.
58///
59/// \details If a fatal error occurs during the boot, the bootloader
60/// calls this function, which must not return. If possible, the
61/// function displays the errorCode in a platform-specific way.
62///
63/// \note
64/// Although it would be nice to decorate the type with "noreturn",
65/// that's not possible in C. But we can mark a function that
66/// calls this as no-return, and then use __builtin_notreached()
67/// in that function.
68///
69typedef void
71 McciBootloaderError_t errorCode
72 );
73
74///
75/// \brief delay execution
76///
77/// \param [in] ms number of milliseconds to delay
78///
79/// \details The bootloader calls this function in order to delay
80/// execution by the specified number of milliseconds. The implementation
81/// may delay longer, but apart errors due to clock inaccuracies, it
82/// should not return appreciably before the specified number of
83/// milliseconds has elapsed.
84///
85typedef void
87 uint32_t ms
88 );
89
90///
91/// \brief Get the "update flag"
92///
93/// The bootloader needs to know if an update has been requested; no
94/// point in scanning storage if we have not been asked to do so.
95///
96/// \returns \c true if we should attempt to update flash from storage, \c false
97/// otherwise.
98///
99typedef bool
101 void
102 );
103
104///
105/// \brief Set the "update flag"
106///
107/// Set the value of the "update flag"
108///
109/// \param [in] state \c true if next boot should attempt to update flash from
110/// storage, \c false otherwise.
111///
112/// \see McciBootloaderPlatform_getUpdateFlagFn_t
113///
114typedef void
116 bool state
117 );
118
119///
120/// \brief Erase a region of internal flash
121///
122/// \param [in] targetAddress base address of region to erase
123/// \param [in] targetSize number of bytes to erase
124///
125/// \p targetAddress and \b targetSize must match the alignment
126/// restritctons of the platform hardware.
127///
128/// \return \c true if region was successfully erased.
129///
130typedef bool
132 volatile const void *targetAddress,
133 size_t targetSize
134 );
135
136///
137/// \brief Program a chunk of internal flash
138///
139/// \param [in] pDestination base address of region to program
140/// \param [in] pSource base address of data to write (in RAM,
141/// for maximum portability)
142/// \param [in] nBytes number of bytes to copy
143///
144/// \p pDestination and \b nBytes must match the alignment
145/// restritctons of the platform hardware. 4k is normally a good
146/// block size.
147///
148/// \return \c true if region was successfully programmed.
149///
150typedef bool
152 volatile const void *pDestination,
153 const void *pSource,
154 size_t nBytes
155 );
156
157///
158/// \brief Initialize the storage driver.
159///
160/// The bootloader calls this prior to doing the first storage access.
161/// Portable drivers can use the SPI APIs to do their work, and should
162/// in turn initialize the SPI driver.
163///
164/// \see McciBootloader_SpiInitFn
165///
166typedef void
168 void
169 );
170
171///
172/// \brief Read bytes from the storage
173///
174/// \param [in] startAddress starting byte address on the storage of data
175/// to be read.
176/// \param [in] pBuffer pointer to buffer to be filled.
177/// \param [in] nBuffer number of bytes to read.
178///
179/// This API is implemented by the storage chip drivers. Often, the storage
180/// chip will have restrictions in terms of address offset and block read
181/// length. The parameters fed to the boot loader and the fact that it reads
182/// 4k blocks (only) should allow most constraints to be honored.
183///
184/// \return \c true if all data was successfully read, \c false if there was
185/// an error
186///
187typedef bool
190 uint8_t *pBuffer,
191 size_t nBuffer
192 );
193
194///
195/// \brief get the start address of the primary image in the storage
196///
199 void
200 );
201
202///
203/// \brief get the start address of the fallback image in the storage
204///
207 void
208 );
209
210///
211/// \brief initialize the SPI driver for storage use
212///
213/// \note This API is only called if a driver decides it intends to use SPI.
214///
215typedef void
217 void
218 );
219
220///
221/// \brief send/receive data over the SPI bus
222///
223/// \param [out] pRx points to the receive data buffer, if not NULL.
224/// \param [in] pTx points to the transmit data buffer, if not NULL.
225/// \param [in] nBytes is the number of bytes to transfer.
226/// \param [in] fContinue indicates whether the chip select is to be left
227/// active after the operation. If \c true, then the chip
228/// select is left active, otherwise it's made inactive.
229///
230/// \details
231/// This API writes and reads data from the SPI bus, optionally leaving the
232/// target device selected.
233///
234/// \p nBytes bytes of data are transferred from the buffer at \p pTx to
235/// the SPI bus, and at the same time are received from the SPI bus to
236/// the buffer at \p pRx.
237///
238/// The parameters \p pRx and \p pTx are optional. If \c NULL, bytes are
239/// discarded or zeroes inserted, respectively.
240///
241/// This API is provided so we can write portable storage chip drivers
242/// that use the SPI bus. It's not used directly by the outer logic
243/// of the bootloader.
244///
245typedef void
247 uint8_t *pRx,
248 const uint8_t *pTx,
249 size_t nBytes,
250 bool fContinue
251 );
252
253///
254/// \brief Initialize the annuciator system
255///
256/// Some boot operations are quite slow. So we allow for a platform to use
257/// the tick interrupt and output information to the user as to how things
258/// are going. This call is made before any state declarations are made to
259/// the annunciator.
260///
261typedef void
263 void
264 );
265
266///
267/// \brief Indicate the current state
268///
269/// \param [in] state the current boot state
270///
271/// Update the curent state for use by the annunciator.
272///
273typedef void
276 );
277
278/// \brief storage interface structure
280McciBootloaderPlatform_StorageInterface_t;
281
282/// \brief SPI interface structure
284McciBootloaderPlatform_SpiInterface_t;
285
286/// \brief annunciator interface structure
288McciBootloaderPlatform_AnnunciatorInterface_t;
289
290
291/// \brief top-level interface structure
293McciBootloaderPlatform_Interface_t;
294
295/// \brief error codes from SVC handler on ARMv6-M systems & such like
296typedef enum McciBootloaderPlatform_ARMv6M_SvcError_e
297 {
298 /// successful processing
300
301 /// error: verify failure
303 /// error: invalid parameter to SVC
305 /// error: SVC isn't just unimplemented, it's unkown to the bootloader
308
310
311/// \brief SVC request codes for boot loader on ARMv6-M systems & such like
312typedef enum McciBootloaderPlatform_ARMv6M_SvcRq_e
313 {
314 /// Fetch pointer to \c uint32_t "update" flag in EEPROM. \c arg1 is pointer to cell to
315 /// receive pointer.
317 /// Call \c mcci_tweetnacl_hashblocks_sha512_init(). \c arg1 is pointer to hash block.
319
320 /// Call \c mcci_tweetnacl_hashblocks_sha512(). \c arg1 points to argument.
321 /// \see McciBootloaderPlatform_ARMv6M_SvcRq_HashBlocks_Arg_t
323
324 /// Call \c mcci_tweetnacl_hashblocks_finish(). \c arg1 points to
325 /// argument.
326 /// \see McciBootloaderPlatform_ARMv6M_SvcRq_HashFinish_Arg_t
328
329 /// Call \c mcci_tweetnacl_verify64(). \c arg1 and \c arg2 are the pointers;
330 /// result is set to verifyFailure for failure.
333
335
336/// \brief argument to \ref McciBootloaderPlatform_ARMv6M_SvcRq_HashBlocks
337typedef struct McciBootloaderPlatform_ARMv6M_SvcRq_HashBlocks_Arg_s
338 {
339 void *pHash;
340 const uint8_t *pMessage;
341 size_t nMessage;
343
344/// \brief argument to \ref McciBootloaderPlatform_ARMv6M_SvcRq_HashFinish
345typedef struct McciBootloaderPlatform_ARMv6M_SvcRq_HashFinish_Arg_s
346 {
347 void *pHash;
348 const uint8_t *pMessage;
349 size_t nMessage;
350 size_t nOverall;
352
353///
354/// \brief SVC function interface
355///
356/// \param [in] svcRequest is the request code.
357/// \param [in] pErrorCode points to a cell to be filled with the error code
358/// (According to the value of \p svcRequest, there may additional
359/// OUT parameters)
360/// \param [in] arg1 is an extra argument, interpreted according to \p svcRequest
361/// \param [in] arg2 is an extra argument, interpreted according to \p svcRequest
362///
363/// \details
364/// This definition lets us take advantage of the ARMv6-M and related
365/// implementations; exception handlers are just like regular subroutines
366/// (except that results have to be passed back by modifying the saved
367/// registers on the stack). We work around this by passing results back
368/// in memory.
369///
370typedef void
374 uint32_t arg1,
375 uint32_t arg2
376 );
377
379#endif /* _mcci_bootloader_platform_types_h_ */
void() McciBootloaderPlatform_FailFn_t(McciBootloaderError_t errorCode)
function for reporting a fatal error
bool() McciBootloaderPlatform_SystemFlashEraseFn_t(volatile const void *targetAddress, size_t targetSize)
Erase a region of internal flash.
void() McciBootloaderPlatform_StorageInitFn_t(void)
Initialize the storage driver.
bool() McciBootloaderPlatform_SystemFlashWriteFn_t(volatile const void *pDestination, const void *pSource, size_t nBytes)
Program a chunk of internal flash.
void() McciBootloaderPlatform_ARMv6M_SvcHandlerFn_t(McciBootloaderPlatform_ARMv6M_SvcRq_t svcRequest, McciBootloaderPlatform_ARMv6M_SvcError_t *pErrorCode, uint32_t arg1, uint32_t arg2)
SVC function interface.
McciBootloaderStorageAddress_t() McciBootloaderPlatform_GetPrimaryStorageAddressFn_t(void)
get the start address of the primary image in the storage
bool() McciBootloaderPlatform_StorageReadFn_t(McciBootloaderStorageAddress_t startAddress, uint8_t *pBuffer, size_t nBuffer)
Read bytes from the storage.
MCCI_BOOTLOADER_BEGIN_DECLS typedef void() McciBootloaderPlatform_SystemInitFn_t(void)
function type for platform intialization function
MCCIADK_C_ASSERT(sizeof(McciBootloaderPlatform_ARMv6M_SvcError_t)==sizeof(uint32_t))
bool() McciBootloaderPlatform_GetUpdateFlagFn_t(void)
Get the "update flag".
void() McciBootloaderPlatform_SetUpdateFlagFn_t(bool state)
Set the "update flag".
void() McciBootloaderPlatform_SpiTransferFn_t(uint8_t *pRx, const uint8_t *pTx, size_t nBytes, bool fContinue)
send/receive data over the SPI bus
void() McciBootloaderPlatform_AnnunciatorInitFn_t(void)
Initialize the annuciator system.
McciBootloaderPlatform_ARMv6M_SvcRq_t
SVC request codes for boot loader on ARMv6-M systems & such like.
@ McciBootloaderPlatform_ARMv6M_SvcRq_HashFinish
Call mcci_tweetnacl_hashblocks_finish().
@ McciBootloaderPlatform_ARMv6M_SvcRq_HashBlocks
Call mcci_tweetnacl_hashblocks_sha512().
@ McciBootloaderPlatform_ARMv6M_SvcRq_GetUpdatePointer
Fetch pointer to uint32_t "update" flag in EEPROM.
@ McciBootloaderPlatform_ARMv6M_SvcRq_HashInit
Call mcci_tweetnacl_hashblocks_sha512_init(). arg1 is pointer to hash block.
@ McciBootloaderPlatform_ARMv6M_SvcRq_Verify64
Call mcci_tweetnacl_verify64().
void() McciBootloaderPlatform_DelayMsFn_t(uint32_t ms)
delay execution
void() McciBootloaderPlatform_SpiInitFn_t(void)
initialize the SPI driver for storage use
void() McciBootloaderPlatform_PrepareForLaunchFn_t(void)
function type for preparing to launch an application
void() McciBootloaderPlatform_AnnunciatorIndicateStateFn_t(McciBootloaderState_t state)
Indicate the current state.
McciBootloaderStorageAddress_t() McciBootloaderPlatform_GetFallbackStorageAddressFn_t(void)
get the start address of the fallback image in the storage
McciBootloaderPlatform_ARMv6M_SvcError_t
error codes from SVC handler on ARMv6-M systems & such like
@ McciBootloaderPlatform_SvcError_VerifyFailure
error: verify failure
@ McciBootloaderPlatform_SvcError_OK
successful processing
@ McciBootloaderPlatform_SvcError_InvalidParameter
error: invalid parameter to SVC
@ McciBootloaderPlatform_SvcError_Unclaimed
error: SVC isn't just unimplemented, it's unkown to the bootloader
#define MCCI_BOOTLOADER_BEGIN_DECLS
#define MCCI_BOOTLOADER_END_DECLS
uint32_t McciBootloaderState_t
Current boot system state.
uint32_t McciBootloaderError_t
error codes for the bootloader
uint32_t McciBootloaderStorageAddress_t
Abstract type for storage byte addresses.
argument to McciBootloaderPlatform_ARMv6M_SvcRq_HashBlocks
argument to McciBootloaderPlatform_ARMv6M_SvcRq_HashFinish
interface structure to platform functions