Implementation of the AWS IoT Over-The-Air Updates Client Library. More...
#include <stddef.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <assert.h>
#include "ota.h"
#include "ota_config.h"
#include "ota_config_defaults.h"
#include "ota_base64_private.h"
#include "ota_platform_interface.h"
#include "ota_private.h"
#include "ota_interface_private.h"
#include "ota_os_interface.h"
#include "core_json.h"
#include "ota_appversion32.h"
Data Structures | |
struct | OtaStateTableEntry_t |
OTA Agent state table entry. More... | |
Macros | |
#define | U16_OFFSET(type, member) ( ( uint16_t ) offsetof( type, member ) ) |
Offset helper. | |
Typedefs | |
typedef OtaErr_t(* | OtaEventHandler_t) (const OtaEventData_t *pEventMsg) |
OTA event handler definition. | |
Functions | |
static IngestResult_t | ingestDataBlock (OtaFileContext_t *pFileContext, const OtaEventData_t *pEventData, OtaPalStatus_t *pCloseResult) |
Ingest a data block. | |
static IngestResult_t | processDataBlock (OtaFileContext_t *pFileContext, uint32_t uBlockIndex, uint32_t uBlockSize, OtaPalStatus_t *pCloseResult, uint8_t *pPayload) |
Validate the incoming data block and store it in the file context. | |
static IngestResult_t | ingestDataBlockCleanup (OtaFileContext_t *pFileContext, OtaPalStatus_t *pCloseResult) |
Free the resources allocated for data ingestion and close the file handle. | |
static OtaFileContext_t * | getFileContextFromJob (const char *pRawMsg, uint32_t messageLength) |
Get the File Context From Job Document. | |
static DocParseErr_t | validateJSON (const char *pJson, uint32_t messageLength) |
Validate JSON document and the DocModel. | |
static DocParseErr_t | extractParameter (JsonDocParam_t docParam, void *pContextBase, const char *pValueInJson, size_t valueLength) |
Store the parameter from the json to the offset specified by the document model. | |
static DocParseErr_t | parseJSONbyModel (const char *pJson, uint32_t messageLength, JsonDocModel_t *pDocModel) |
Extract the desired fields from the JSON document based on the specified document model. | |
static DocParseErr_t | decodeAndStoreKey (const char *pValueInJson, size_t valueLength, void *pParamAdd) |
Decode the base64 encoded file signature key from the job document and store it in file context. | |
static DocParseErr_t | extractAndStoreArray (const char *pKey, const char *pValueInJson, size_t valueLength, void *pParamAdd, const uint32_t *pParamSizeAdd) |
Extract the value from json and store it into the allocated memory. | |
static DocParseErr_t | verifyRequiredParamsExtracted (const JsonDocParam_t *pModelParam, const JsonDocModel_t *pDocModel) |
Check if all the required parameters for job document are extracted from the JSON. | |
static OtaErr_t | validateUpdateVersion (const OtaFileContext_t *pFileContext) |
Validate the version of the update received. | |
static OtaJobParseErr_t | handleCustomJob (const char *pJson, uint32_t messageLength) |
Check if the JSON can be parsed through the app callback if initial parsing fails. | |
static OtaJobParseErr_t | verifyActiveJobStatus (OtaFileContext_t *pFileContext, OtaFileContext_t **pFinalFile, bool *pUpdateJob) |
Check if the incoming job document is not conflicting with current job status. | |
static OtaJobParseErr_t | validateAndStartJob (OtaFileContext_t *pFileContext, OtaFileContext_t **pFinalFile, bool *pUpdateJob) |
Check if all the file context params are valid and initialize resources for the job transfer. | |
static OtaFileContext_t * | parseJobDoc (const JsonDocParam_t *pJsonExpectedParams, uint16_t numJobParams, const char *pJson, uint32_t messageLength, bool *pUpdateJob) |
Parse the OTA job document, validate and return the populated OTA context if valid. | |
static bool | validateDataBlock (const OtaFileContext_t *pFileContext, uint32_t blockIndex, uint32_t blockSize) |
Validate block index and block size of the data block. | |
static IngestResult_t | decodeAndStoreDataBlock (const OtaFileContext_t *pFileContext, const uint8_t *pRawMsg, uint32_t messageSize, uint8_t **pPayload, uint32_t *pBlockSize, uint32_t *pBlockIndex) |
Decode and ingest the incoming data block. | |
static bool | otaClose (OtaFileContext_t *const pFileContext) |
Close an open OTA file context and free it. | |
static void | otaTimerCallback (OtaTimerId_t otaTimerId) |
OTA Timer callback. | |
static OtaErr_t | setImageStateWithReason (OtaImageState_t stateToSet, uint32_t reasonToSet) |
Internal function to set the image state including an optional reason code. | |
static OtaErr_t | updateJobStatusFromImageState (OtaImageState_t state, int32_t subReason) |
Internal function to update the job status to the jobs service from current image state. | |
static void | agentShutdownCleanup (void) |
A helper function to cleanup resources during OTA agent shutdown. | |
static void | dataHandlerCleanup (void) |
A helper function to cleanup resources when data ingestion is complete. | |
static DocParseErr_t | initDocModel (JsonDocModel_t *pDocModel, const JsonDocParam_t *pBodyDef, void *contextBaseAddr, uint32_t contextSize, uint16_t numJobParams) |
Prepare the document model for use by sanity checking the initialization parameters and detecting all required parameters. | |
static void | initializeAppBuffers (const OtaAppBuffer_t *pOtaBuffer) |
Initialize buffers for storing the file attributes. | |
static void | initializeLocalBuffers (void) |
Initialize jobId and protocol buffers. | |
static uint32_t | searchTransition (const OtaEventMsg_t *pEventMsg) |
Search the state transition table for the entry based on current state and incoming event. | |
static OtaErr_t | processValidFileContext (void) |
Initiate download if not in self-test else reboot. | |
static void | handleSelfTestJobDoc (const OtaFileContext_t *pFileContext) |
Validate update version when receiving job doc in self test state. | |
static OtaErr_t | processNullFileContext (void) |
Handle invalid file context. | |
static bool | platformInSelftest (void) |
Check if the platform is in self-test. | |
static void | handleUnexpectedEvents (const OtaEventMsg_t *pEventMsg) |
Function to handle events that were unexpected in the current state. | |
static void | freeFileContextMem (OtaFileContext_t *const pFileContext) |
Free or clear multiple buffers used in the file context. | |
static void | handleJobParsingError (const OtaFileContext_t *pFileContext, OtaJobParseErr_t err) |
Handle job parsing error. | |
static void | receiveAndProcessOtaEvent (void) |
Receive and process the next available event from the event queue. | |
static void | callOtaCallback (OtaJobEvent_t eEvent, void *pData) |
Call OTA callback function if it's registered. | |
static void | resetEventQueue (void) |
Clear all messages in the event queue. | |
static OtaErr_t | startHandler (const OtaEventData_t *pEventData) |
static OtaErr_t | requestJobHandler (const OtaEventData_t *pEventData) |
static OtaErr_t | processJobHandler (const OtaEventData_t *pEventData) |
static OtaErr_t | inSelfTestHandler (const OtaEventData_t *pEventData) |
static OtaErr_t | initFileHandler (const OtaEventData_t *pEventData) |
static OtaErr_t | processDataHandler (const OtaEventData_t *pEventData) |
static OtaErr_t | requestDataHandler (const OtaEventData_t *pEventData) |
static OtaErr_t | shutdownHandler (const OtaEventData_t *pEventData) |
static OtaErr_t | closeFileHandler (const OtaEventData_t *pEventData) |
static OtaErr_t | userAbortHandler (const OtaEventData_t *pEventData) |
static OtaErr_t | suspendHandler (const OtaEventData_t *pEventData) |
static OtaErr_t | resumeHandler (const OtaEventData_t *pEventData) |
static OtaErr_t | jobNotificationHandler (const OtaEventData_t *pEventData) |
static void | executeHandler (uint32_t index, const OtaEventMsg_t *const pEventMsg) |
void | OTA_EventProcessingTask (const void *pUnused) |
OTA agent event processing loop. | |
OtaState_t | OTA_EventProcess (void) |
OTA agent event process cycler. | |
bool | OTA_SignalEvent (const OtaEventMsg_t *const pEventMsg) |
Signal event to the OTA Agent task. | |
OtaErr_t | OTA_Init (const OtaAppBuffer_t *pOtaBuffer, const OtaInterfaces_t *pOtaInterfaces, const uint8_t *pThingName, OtaAppCallback_t OtaAppCallback) |
OTA Agent initialization function. | |
OtaState_t | OTA_Shutdown (uint32_t ticksToWait, uint8_t unsubscribeFlag) |
Signal to the OTA Agent to shut down. | |
OtaState_t | OTA_GetState (void) |
Get the current state of the OTA agent. | |
OtaErr_t | OTA_GetStatistics (OtaAgentStatistics_t *pStatistics) |
Get the statistics of OTA message packets. | |
OtaErr_t | OTA_CheckForUpdate (void) |
Request for the next available OTA job from the job service. | |
OtaErr_t | OTA_ActivateNewImage (void) |
Activate the newest MCU image received via OTA. | |
OtaErr_t | OTA_SetImageState (OtaImageState_t state) |
Set the state of the current MCU image. | |
OtaImageState_t | OTA_GetImageState (void) |
Get the state of the currently running MCU image. | |
OtaErr_t | OTA_Suspend (void) |
Suspend OTA agent operations . | |
OtaErr_t | OTA_Resume (void) |
Resume OTA agent operations . | |
const char * | OTA_Err_strerror (OtaErr_t err) |
Error code to string conversion for OTA errors. | |
const char * | OTA_JobParse_strerror (OtaJobParseErr_t err) |
Error code to string conversion for OTA Job Parsing errors. | |
const char * | OTA_OsStatus_strerror (OtaOsStatus_t status) |
Status code to string conversion for OTA OS status. | |
const char * | OTA_PalStatus_strerror (OtaPalMainStatus_t status) |
Status code to string conversion for OTA PAL status. | |
Variables | |
static OtaControlInterface_t | otaControlInterface |
OTA control interface. | |
static OtaDataInterface_t | otaDataInterface |
OTA data interface. | |
static OtaAgentContext_t | otaAgent |
This is THE OTA agent context and initialization state. | |
static OtaStateTableEntry_t | otaTransitionTable [] |
Transition table for the OTA state machine. | |
static const char * | pOtaAgentStateStrings [OtaAgentStateAll+1] |
String set to represent the States of the OTA agent. | |
static const char * | pOtaEventStrings [OtaAgentEventMax] |
String set to represent the Events for the OTA agent. | |
static const JsonDocParam_t | otaJobDocModelParamStructure [OTA_NUM_JOB_PARAMS] |
This is the OTA job document model describing the parameters, their types, destination and how to extract. | |
static uint8_t | pJobNameBuffer [OTA_JOB_ID_MAX_SIZE] |
static uint8_t | pProtocolBuffer [OTA_PROTOCOL_BUFFER_SIZE] |
static Sig_t | sigBuffer |
Implementation of the AWS IoT Over-The-Air Updates Client Library.
|
static |
Ingest a data block.
A block of file data was received by the application via some configured communication protocol. If it looks like it is in range, write it to persistent storage. If it's the last block we're expecting, close the file and perform the final signature check on it. If the close and signature check are OK, let the caller know so it can be used by the system. Firmware updates generally reboot the system and perform a self test phase. If the close or signature check fails, abort the file transfer and return the result and any available details to the caller.
[in] | pFileContext | Information of file to be streamed. |
[in] | pEventData | The event data containing the job document. |
[in] | pCloseResult | Result of closing file in PAL. |
|
static |
Validate the incoming data block and store it in the file context.
[in] | pFileContext | Information of file to be streamed. |
[in] | uBlockIndex | Incoming block index. |
[in] | uBlockSize | Incoming block size. |
[out] | pCloseResult | Result of closing file in PAL. |
[in] | pPayload | Data from the block. |
|
static |
Free the resources allocated for data ingestion and close the file handle.
[in] | pFileContext | Information of file to be streamed. |
[out] | pCloseResult | Result of closing file in PAL. |
|
static |
Get the File Context From Job Document.
We received an OTA update job message from the job service so process the message and update the file context.
[in] | pRawMsg | Raw job document. |
[in] | messageLength | length of document. |
|
static |
Validate JSON document and the DocModel.
[in] | pJson | JSON job document. |
[in] | messageLength | Length of the job document. |
|
static |
Store the parameter from the json to the offset specified by the document model.
[in] | docParam | Structure to store the details of keys and where to store them. |
[in] | pContextBase | Start of file context. |
[in] | pValueInJson | Pointer to the value of the key in JSON buffer. |
[in] | valueLength | Length of the value. |
|
static |
Extract the desired fields from the JSON document based on the specified document model.
[in] | pJson | JSON job document. |
[in] | messageLength | Length of the job document. |
[in] | pDocModel | Details of expected parameters in the job doc. |
|
static |
Decode the base64 encoded file signature key from the job document and store it in file context.
[in] | pValueInJson | Pointer to the value of the key in JSON buffer. |
[in] | valueLength | Length of the value. |
[out] | pParamAdd | Pointer to the location where the value is stored. |
|
static |
Extract the value from json and store it into the allocated memory.
[in] | pKey | Name of the Key to extract. |
[in] | pValueInJson | Pointer to the value of the key in JSON buffer. |
[in] | valueLength | Length of the value. |
[out] | pParamAdd | Pointer to the location where the value is stored. |
[in] | pParamSizeAdd | Size required to store the param. |
|
static |
Check if all the required parameters for job document are extracted from the JSON.
[in] | pModelParam | Structure to store the details of keys and where to store them. |
[in] | pDocModel | Details of expected parameters in the job doc. |
|
static |
Validate the version of the update received.
[in] | pFileContext | Information of file to be streamed. |
|
static |
Check if the JSON can be parsed through the app callback if initial parsing fails.
[in] | pJson | JSON job document. |
[in] | messageLength | Length of the job document. |
|
static |
Check if the incoming job document is not conflicting with current job status.
[in] | pFileContext | Information of file to be streamed. |
[out] | pFinalFile | File that stores all extracted params. |
[out] | pUpdateJob | Represents if the job is accepted. |
|
static |
Check if all the file context params are valid and initialize resources for the job transfer.
[in] | pFileContext | Information of file to be streamed. |
[out] | pFinalFile | File that stores all extracted params. |
[out] | pUpdateJob | Represents if the job is accepted. |
|
static |
Parse the OTA job document, validate and return the populated OTA context if valid.
[in] | pJsonExpectedParams | Structure to store the details of keys and where to store them. |
[in] | numJobParams | Number of parameters to be extracted. |
[in] | pJson | JSON job document. |
[in] | messageLength | Length of the job document. |
[in] | pUpdateJob | Represents if the job is accepted. |
|
static |
Validate block index and block size of the data block.
[in] | pFileContext | Information of file to be streamed. |
[in] | blockIndex | Block index of incoming data block. |
[in] | blockSize | Block size of incoming data block. |
|
static |
Decode and ingest the incoming data block.
[in] | pFileContext | Information of file to be streamed. |
[in] | pRawMsg | Raw job document. |
[in] | messageSize | Length of document. |
[in] | pPayload | Data stored in the document. |
[out] | pBlockSize | Block size of incoming data block. |
[out] | pBlockIndex | Block index of incoming data block. |
|
static |
Close an open OTA file context and free it.
[in] | pFileContext | Information of file to be streamed. |
|
static |
OTA Timer callback.
[in] | otaTimerId | Reference to the timer to use. |
|
static |
Internal function to set the image state including an optional reason code.
[in] | stateToSet | State to set. |
[in] | reasonToSet | Reason to set. |
|
static |
Internal function to update the job status to the jobs service from current image state.
[in] | state | State to set. |
[in] | subReason | Reason for status. |
|
static |
Prepare the document model for use by sanity checking the initialization parameters and detecting all required parameters.
[in,out] | pDocModel | Details of expected parameters in the job doc. |
[in] | pBodyDef | Structure to store the details of keys and where to store them. |
[in] | contextBaseAddr | Start of file context. |
[in] | contextSize | Size of file context. |
[in] | numJobParams | Number of parameters to be extracted. |
|
static |
Initialize buffers for storing the file attributes.
[out] | pOtaBuffer | OTA Application buffers. |
|
static |
Search the state transition table for the entry based on current state and incoming event.
[in] | pEventMsg | Incoming event information. |
|
static |
Initiate download if not in self-test else reboot.
|
static |
Validate update version when receiving job doc in self test state.
[in] | pFileContext | Stores file information. |
|
static |
Handle invalid file context.
|
static |
Check if the platform is in self-test.
|
static |
Function to handle events that were unexpected in the current state.
[in] | pEventMsg | Stores information of the event. |
|
static |
Free or clear multiple buffers used in the file context.
[in] | pFileContext | Information of file to be streamed. |
|
static |
Handle job parsing error.
[in] | pFileContext | Pointer to the file context. |
[in] | err | Parsing error of type OtaJobParseErr_t. |
|
static |
Receive and process the next available event from the event queue.
Each event is processed based on the behavior defined in the OTA transition table. The state of the OTA state machine will be updated and the corresponding event handler will be called.
|
static |
Start timers and initiate request for job document.
|
static |
Initiate a request for a job.
|
static |
Update file context from job document.
|
static |
Handle self test.
|
static |
Initialize and handle file transfer.
|
static |
Process incoming data blocks.
|
static |
Request for data blocks.
|
static |
Shutdown OTA and cleanup.
|
static |
Close file opened for download.
|
static |
Handle user interrupt to abort task.
|
static |
Handle suspend event for OTA agent.
|
static |
Resume from a suspended state.
|
static |
Upon receiving a new job document cancel current job if present and initiate new download.
|
static |
Execute the handler for selected index from the transition table.
void OTA_EventProcessingTask | ( | const void * | pUnused | ) |
OTA agent event processing loop.
This is the main event loop to handle events for OTA update and needs to be called by the application task. This loop will continue to handle and execute events received for OTA Update until this tasks is terminated by the application.
[in] | pUnused | Can be used to pass down functionality to the agent task, Unused for now. This can be a function pointer that executes as the first routine when the event loop starts. |
For a Posix based reference of creating a thread with this task, please see the demos in AWS IoT Embedded C SDK repository.
OtaState_t OTA_EventProcess | ( | void | ) |
OTA agent event process cycler.
This is the main agent event handler for OTA update and needs to be called repeatedly by an application task. This is functionally equivalent to OTA_EventProcessingTask, except instead of forever looping internally, the user is responsible for periodically calling this function.
bool OTA_SignalEvent | ( | const OtaEventMsg_t *const | pEventMsg | ) |
Signal event to the OTA Agent task.
This function adds the event to the back of event queue and used by internal OTA modules to signal agent task.
[in] | pEventMsg | Event to be added to the queue |
Example Signal OTA agent that a new file block has been received over the http connection.
OtaErr_t OTA_Init | ( | const OtaAppBuffer_t * | pOtaBuffer, |
const OtaInterfaces_t * | pOtaInterfaces, | ||
const uint8_t * | pThingName, | ||
OtaAppCallback_t | OtaAppCallback | ||
) |
OTA Agent initialization function.
Initialize the OTA engine by starting the OTA Agent ("OTA Task") in the system. This function must be called with the connection client context before calling OTA_CheckForUpdate. Only one OTA Agent may exist.
[in] | pOtaBuffer | Buffers used by the agent to store different params. |
[in] | pOtaInterfaces | A pointer to the OS context. |
[in] | pThingName | A pointer to a C string holding the Thing name. |
[in] | OtaAppCallback | Static callback function for when an OTA job is complete. This function will have input of the state of the OTA image after download and during self-test. |
Example
OtaState_t OTA_Shutdown | ( | uint32_t | ticksToWait, |
uint8_t | unsubscribeFlag | ||
) |
Signal to the OTA Agent to shut down.
Signals the OTA agent task to shut down. The OTA agent will unsubscribe from all MQTT job notification topics, stop in progress OTA jobs, if any, and clear all resources.
OTA needs a processing task running OTA_EventProcessingTask to handle shutdown event, or OTA will shutdown after the processing task is created and scheduled.
[in] | ticksToWait | The number of ticks to wait for the OTA Agent to complete the shutdown process. If this is set to zero, the function will return immediately without waiting. The actual state is returned to the caller. The agent does not sleep for this while but used for busy looping. |
[in] | unsubscribeFlag | Flag to indicate if unsubscribe operations should be performed from the job topics when shutdown is called. If the flag is 0 then unsubscribe operations are not called for job topics If application requires it to be unsubscribed from the job topics then flag must be set to 1 when calling OTA_Shutdown. |
Example
OtaState_t OTA_GetState | ( | void | ) |
Get the current state of the OTA agent.
Example Check if OTA agent is in suspended state.
OtaErr_t OTA_GetStatistics | ( | OtaAgentStatistics_t * | pStatistics | ) |
Get the statistics of OTA message packets.
Packet statistics are:
Example
OtaErr_t OTA_CheckForUpdate | ( | void | ) |
Request for the next available OTA job from the job service.
OtaErr_t OTA_ActivateNewImage | ( | void | ) |
Activate the newest MCU image received via OTA.
This function should reset the MCU and cause a reboot of the system to execute the newly updated firmware. It should be called by the user code sometime after the OtaJobEventActivate event is passed to the users application via the OTA Job Complete Callback mechanism. Refer to the OTA_Init function for more information about configuring the callback.
Example
OtaErr_t OTA_SetImageState | ( | OtaImageState_t | state | ) |
Set the state of the current MCU image.
The states are OtaImageStateTesting, OtaImageStateAccepted, OtaImageStateAborted or OtaImageStateRejected; see OtaImageState_t documentation. This will update the status of the current image and publish to the active job status topic.
[in] | state | The state to set of the OTA image. |
Example Set image state to reflect new image is accepted in application callback.
OtaImageState_t OTA_GetImageState | ( | void | ) |
Get the state of the currently running MCU image.
The states are OtaImageStateTesting, OtaImageStateAccepted, OtaImageStateAborted or OtaImageStateRejected; see OtaImageState_t documentation.
OtaErr_t OTA_Suspend | ( | void | ) |
Suspend OTA agent operations .
Example Suspend the OTA agent when a network error occurs.
OtaErr_t OTA_Resume | ( | void | ) |
Resume OTA agent operations .
Example Resume the OTA agent after the network errors are resolved.
const char * OTA_Err_strerror | ( | OtaErr_t | err | ) |
Error code to string conversion for OTA errors.
[in] | err | The error to convert to a string. |
const char * OTA_JobParse_strerror | ( | OtaJobParseErr_t | err | ) |
Error code to string conversion for OTA Job Parsing errors.
[in] | err | The error to convert to a string. |
const char * OTA_OsStatus_strerror | ( | OtaOsStatus_t | status | ) |
Status code to string conversion for OTA OS status.
[in] | status | The status to convert to a string. |
const char * OTA_PalStatus_strerror | ( | OtaPalMainStatus_t | status | ) |
Status code to string conversion for OTA PAL status.
[in] | status | The status to convert to a string. |
|
static |
This is THE OTA agent context and initialization state.
|
static |
Transition table for the OTA state machine.
|
static |
String set to represent the States of the OTA agent.
|
static |
String set to represent the Events for the OTA agent.
|
static |
This is the OTA job document model describing the parameters, their types, destination and how to extract.
|
static |
Buffer to store job name.
|
static |
Buffer to store data protocol.
|
static |
Buffer to store key file signature.