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 current millisecond tick count
92///
93/// \details The bootloader calls this function in order to get a monotonically
94/// incrementing count of milliseconds. This is primarily used for timeouts.
95/// In general, we have a clock tick interrupt running that is used
96/// for modulating the LED during boot, however the rest of the bootloader
97/// doesn't care about how this is actually implemented. Timeout loops are
98/// the main users of this API, so it's possible to implement this by watching
99/// changes in a counter register. The actual timebase is not critical,
100/// but to avoid premature timeouts, the returned counter should not advance
101/// faster than real time.
102///
105 void
106 );
107
108///
109/// \brief Get the "update flag"
110///
111/// The bootloader needs to know if an update has been requested; no
112/// point in scanning storage if we have not been asked to do so.
113///
114/// \returns \c true if we should attempt to update flash from storage, \c false
115/// otherwise.
116///
117typedef bool
119 void
120 );
121
122///
123/// \brief Set the "update flag"
124///
125/// Set the value of the "update flag"
126///
127/// \param [in] state \c true if next boot should attempt to update flash from
128/// storage, \c false otherwise.
129///
130/// \see McciBootloaderPlatform_getUpdateFlagFn_t
131///
132typedef void
134 bool state
135 );
136
137///
138/// \brief Erase a region of internal flash
139///
140/// \param [in] targetAddress base address of region to erase
141/// \param [in] targetSize number of bytes to erase
142///
143/// \p targetAddress and \b targetSize must match the alignment
144/// restritctons of the platform hardware.
145///
146/// \return \c true if region was successfully erased.
147///
148typedef bool
150 volatile const void *targetAddress,
151 size_t targetSize
152 );
153
154///
155/// \brief Program a chunk of internal flash
156///
157/// \param [in] pDestination base address of region to program
158/// \param [in] pSource base address of data to write (in RAM,
159/// for maximum portability)
160/// \param [in] nBytes number of bytes to copy
161///
162/// \p pDestination and \b nBytes must match the alignment
163/// restritctons of the platform hardware. 4k is normally a good
164/// block size.
165///
166/// \return \c true if region was successfully programmed.
167///
168typedef bool
170 volatile const void *pDestination,
171 const void *pSource,
172 size_t nBytes
173 );
174
175///
176/// \brief Initialize the storage driver.
177///
178/// The bootloader calls this prior to doing the first storage access.
179/// Portable drivers can use the SPI APIs to do their work, and should
180/// in turn initialize the SPI driver.
181///
182/// \see McciBootloader_SpiInitFn
183///
184typedef void
186 void
187 );
188
189///
190/// \brief Read bytes from the storage
191///
192/// \param [in] startAddress starting byte address on the storage of data
193/// to be read.
194/// \param [in] pBuffer pointer to buffer to be filled.
195/// \param [in] nBuffer number of bytes to read.
196///
197/// This API is implemented by the storage chip drivers. Often, the storage
198/// chip will have restrictions in terms of address offset and block read
199/// length. The parameters fed to the boot loader and the fact that it reads
200/// 4k blocks (only) should allow most constraints to be honored.
201///
202/// \return \c true if all data was successfully read, \c false if there was
203/// an error
204///
205typedef bool
208 uint8_t *pBuffer,
209 size_t nBuffer
210 );
211
212///
213/// \brief get the start address of the primary image in the storage
214///
217 void
218 );
219
220///
221/// \brief get the start address of the fallback image in the storage
222///
225 void
226 );
227
228///
229/// \brief initialize the SPI driver for storage use
230///
231/// \note This API is only called if a driver decides it intends to use SPI.
232///
233typedef void
235 void
236 );
237
238///
239/// \brief send/receive data over the SPI bus
240///
241/// \param [out] pRx points to the receive data buffer, if not NULL.
242/// \param [in] pTx points to the transmit data buffer, if not NULL.
243/// \param [in] nBytes is the number of bytes to transfer.
244/// \param [in] fContinue indicates whether the chip select is to be left
245/// active after the operation. If \c true, then the chip
246/// select is left active, otherwise it's made inactive.
247///
248/// \details
249/// This API writes and reads data from the SPI bus, optionally leaving the
250/// target device selected.
251///
252/// \p nBytes bytes of data are transferred from the buffer at \p pTx to
253/// the SPI bus, and at the same time are received from the SPI bus to
254/// the buffer at \p pRx.
255///
256/// The parameters \p pRx and \p pTx are optional. If \c NULL, bytes are
257/// discarded or zeroes inserted, respectively.
258///
259/// This API is provided so we can write portable storage chip drivers
260/// that use the SPI bus. It's not used directly by the outer logic
261/// of the bootloader.
262///
263typedef void
265 uint8_t *pRx,
266 const uint8_t *pTx,
267 size_t nBytes,
268 bool fContinue
269 );
270
271///
272/// \brief Initialize the annuciator system
273///
274/// Some boot operations are quite slow. So we allow for a platform to use
275/// the tick interrupt and output information to the user as to how things
276/// are going. This call is made before any state declarations are made to
277/// the annunciator.
278///
279typedef void
281 void
282 );
283
284///
285/// \brief Indicate the current state
286///
287/// \param [in] state the current boot state
288///
289/// Update the curent state for use by the annunciator.
290///
291typedef void
294 );
295
296/// \brief storage interface structure
298McciBootloaderPlatform_StorageInterface_t;
299
300/// \brief SPI interface structure
302McciBootloaderPlatform_SpiInterface_t;
303
304/// \brief annunciator interface structure
306McciBootloaderPlatform_AnnunciatorInterface_t;
307
308
309/// \brief top-level interface structure
311McciBootloaderPlatform_Interface_t;
312
313/// \brief error codes from SVC handler on ARMv6-M systems & such like
314typedef enum McciBootloaderPlatform_ARMv6M_SvcError_e
315 {
316 /// successful processing
318
319 /// error: verify failure
321 /// error: invalid parameter to SVC
323 /// error: SVC isn't just unimplemented, it's unkown to the bootloader
326
328
329/// \brief SVC request codes for boot loader on ARMv6-M systems & such like
330typedef enum McciBootloaderPlatform_ARMv6M_SvcRq_e
331 {
332 /// Fetch pointer to \c uint32_t "update" flag in EEPROM. \c arg1 is pointer to cell to
333 /// receive pointer.
335 /// Call \c mcci_tweetnacl_hashblocks_sha512_init(). \c arg1 is pointer to hash block.
337
338 /// Call \c mcci_tweetnacl_hashblocks_sha512(). \c arg1 points to argument.
339 /// \see McciBootloaderPlatform_ARMv6M_SvcRq_HashBlocks_Arg_t
341
342 /// Call \c mcci_tweetnacl_hashblocks_finish(). \c arg1 points to
343 /// argument.
344 /// \see McciBootloaderPlatform_ARMv6M_SvcRq_HashFinish_Arg_t
346
347 /// Call \c mcci_tweetnacl_verify64(). \c arg1 and \c arg2 are the pointers;
348 /// result is set to verifyFailure for failure.
351
353
354/// \brief argument to \ref McciBootloaderPlatform_ARMv6M_SvcRq_HashBlocks
355typedef struct McciBootloaderPlatform_ARMv6M_SvcRq_HashBlocks_Arg_s
356 {
357 void *pHash;
358 const uint8_t *pMessage;
359 size_t nMessage;
361
362/// \brief argument to \ref McciBootloaderPlatform_ARMv6M_SvcRq_HashFinish
363typedef struct McciBootloaderPlatform_ARMv6M_SvcRq_HashFinish_Arg_s
364 {
365 void *pHash;
366 const uint8_t *pMessage;
367 size_t nMessage;
368 size_t nOverall;
370
371///
372/// \brief SVC function interface
373///
374/// \param [in] svcRequest is the request code.
375/// \param [in] pErrorCode points to a cell to be filled with the error code
376/// (According to the value of \p svcRequest, there may additional
377/// OUT parameters)
378/// \param [in] arg1 is an extra argument, interpreted according to \p svcRequest
379/// \param [in] arg2 is an extra argument, interpreted according to \p svcRequest
380///
381/// \details
382/// This definition lets us take advantage of the ARMv6-M and related
383/// implementations; exception handlers are just like regular subroutines
384/// (except that results have to be passed back by modifying the saved
385/// registers on the stack). We work around this by passing results back
386/// in memory.
387///
388typedef void
392 uint32_t arg1,
393 uint32_t arg2
394 );
395
397#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
McciBootloader_Milliseconds_t() McciBootloaderPlatform_GetMillisecondsFn_t(void)
get current millisecond tick count
#define MCCI_BOOTLOADER_BEGIN_DECLS
#define MCCI_BOOTLOADER_END_DECLS
uint32_t McciBootloader_Milliseconds_t
Time (in milliseconds)
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