Adding Metadata to GBL Files

Introduction

Metadata

Metadata can be anything that can be put into a byte array. You can add text, structures, or binary data to your GBL files. Hence, when you update your device with a new firmware, you can also update other settings, e.g., a parameter set, that is stored in the persistent storage. You can also send extended version information along with the firmware or you can send new security keys in a signed and encrypted GBL file. You can even send an extra firmware image as metadata intended to be sent to another device.

Adding Metadata to the GBL File

Metadata can be added when you create the GBL file with the „commander gbl create” command. Add the --metadata switch and the name of the file, that contains the metadata. For example:

commander gbl create application.gbl --app application.s37 --metadata metadata.bin

If you use the create_bl_files.bat file to create GBL files, edit the file and extend the commands with the --metadata switch.

Reading Metadata from the Uploaded Files

You can read the content of the metadata that was put into the GBL file as follows:

Note: Neither version is supported by the Bluetooth stack AppLoader because AppLoader decodes the GBL file on-the-fly, does not store the full GBL file anywhere, and does not allow accessing the metadata. To access metadata, implement an application level OTA DFU, as described in Implementing OTA Firmware Update in User Application and Uploading Images to Internal/External Flash Using OTA DFU.

Note that the application level OTA DFU can be used only in a device with an internal flash larger than 256k or with a device that has an external flash.

Reading Metadata on-the-fly

When you upload a new firmware image, you will receive the image in chunks. These chunks are received by the application and they can be written into any storage slot using the API of Gecko Bootloader. At the same time, when you get a chunk of the uploaded image, you can run the GBL parser on it, using the API of Gecko Bootloader. When the parser finds metadata in the GBL file, it calls a callback function and passes metadata to this function. Note the following:

To initialize the GBL parser, use the following code:

#define BTL_PARSER_CTX_SZ  0x200
static uint8_t parserContext[BTL_PARSER_CTX_SZ];
static BootloaderParserCallbacks_t parserCallbacks;

parserCallbacks.applicationCallback = NULL;
parserCallbacks.bootloaderCallback = NULL;
parserCallbacks.metadataCallback = metadataCallback;
bootloader_init();
bootloader_initParser((BootloaderParserContext_t *)parserContext,BTL_PARSER_CTX_SZ);

Note that the parser context size must be at least 384 bytes.

To run the parser on a received chunk of data (data,len), use the following command:

bootloader_parseBuffer((BootloaderParserContext_t *)parserContext,&parserCallbacks,data,len);

Finally, define the callback function, as follows:

void metadataCallback(uint32_t address, uint8_t *data, size_t length, void *context)
{
       //process the received chunk of metadata (data,length)
}

Reading Metadata from a Stored GBL File

A much easier solution, compared to on-the-fly parsing, is to retrieve the metadata from an already stored GBL file. To do so, first upload the GBL file without decoding it into a storage slot, defined by the bootloader. To retrieve the metadata from a GBL file stored in a storage slot, call the following function:

bootloader_verifyImage(slotID,metadataCallback);

and define the callback function, as follows:

void metadataCallback(uint32_t address, uint8_t *data, size_t length, void *context)
{
       //process the received chunk of metadata (data,length)
}

Note that, although the whole GBL file is available in the storage slot, you will still get metadata in chunks because the parser has a limited buffer. The maximum size of a chunk is 64 bytes.

Implementing the Callback Function

The metadata callback function is called several times and provides metadata in chunks. The callback function receives four parameters, as follows:

To assemble metadata from the chunks, use the following code snippet:

#define MAX_METADATA_LENGTH   512
uint8_t metadata[MAX_METADATA_LENGTH];

void metadataCallback(uint32_t address, uint8_t *data, size_t length, void *context)
{
    uint8_t i;

    for (i = 0; i < MIN(length , MAX_METADATA_LENGTH - address); i++)
    {
        metadata[address + i] = data[i];
    }
}