Simulated product dispenser

Dependencies:   HTS221

Fork of mbed-cloud-workshop-connect-HTS221 by Jim Carver

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers arm_uc_source_manager.c Source File

arm_uc_source_manager.c

00001 // ----------------------------------------------------------------------------
00002 // Copyright 2016-2017 ARM Ltd.
00003 //
00004 // SPDX-License-Identifier: Apache-2.0
00005 //
00006 // Licensed under the Apache License, Version 2.0 (the "License");
00007 // you may not use this file except in compliance with the License.
00008 // You may obtain a copy of the License at
00009 //
00010 //     http://www.apache.org/licenses/LICENSE-2.0
00011 //
00012 // Unless required by applicable law or agreed to in writing, software
00013 // distributed under the License is distributed on an "AS IS" BASIS,
00014 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00015 // See the License for the specific language governing permissions and
00016 // limitations under the License.
00017 // ----------------------------------------------------------------------------
00018 
00019 #include "update-client-source-manager/arm_uc_source_manager.h"
00020 
00021 #include "update-client-common/arm_uc_common.h"
00022 #include "update-client-source/arm_uc_source.h"
00023 
00024 #include <stdint.h>
00025 #include <stdlib.h>
00026 
00027 static const ARM_UPDATE_SOURCE* source_registry[MAX_SOURCES];
00028 static ARM_SOURCE_SignalEvent_t event_cb;
00029 
00030 // storage set aside for adding event_cb to the event queue
00031 static arm_uc_callback_t event_cb_storage = { 0 };
00032 
00033 typedef enum {
00034     QUERY_TYPE_UNKNOWN,
00035     QUERY_TYPE_MANIFEST_DEFAULT,
00036     QUERY_TYPE_MANIFEST_URL,
00037     QUERY_TYPE_FIRMWARE,
00038     QUERY_TYPE_KEYTABLE
00039 } query_type_t;
00040 
00041 typedef struct {
00042     arm_uc_uri_t *uri;             // the uri from which the resourced should be fetched
00043     arm_uc_buffer_t *buffer;       // buffer given by caller to contain the results of the fetch
00044     uint32_t offset;               // offset parameter passed to the source
00045     query_type_t type;             // type of request, whether is manifest, firmware or keytable
00046     uint8_t excludes[MAX_SOURCES]; // records the tried and failed sources during a get request
00047     uint8_t current_source;        // records the index of source use in the get request in progress
00048 } request_t;
00049 
00050 // Hold information about the request in flight, there will always only be one request in flight
00051 static request_t request_in_flight;
00052 
00053 /* ==================================================================== *
00054  * Private Functions                                                    *
00055  * ==================================================================== */
00056 
00057 /**
00058  * @brief Initialise a request_t struct, called when a new request
00059  *        have been initiated from the hub
00060  */
00061 static arm_uc_error_t ARM_UCSM_RequestStructInit(request_t* request);
00062 
00063 /**
00064  * @brief The SourceRegistry is an array of ARM_UPDATE_SOURCE
00065  */
00066 static arm_uc_error_t ARM_UCSM_SourceRegistryInit(void);
00067 static arm_uc_error_t ARM_UCSM_SourceRegistryAdd(const ARM_UPDATE_SOURCE* source);
00068 static arm_uc_error_t ARM_UCSM_SourceRegistryRemove(const ARM_UPDATE_SOURCE* source);
00069 
00070 /**
00071  * @brief return the index of the source with the smallest cost
00072  * @param url Struct containing URL. NULL for default Manifest.
00073  * @param type The type of current request.
00074  * @param excludes Pointer to an array of size MAX_SOURCES to indicate
00075  *                 sources we want to exclude in the search. Set excludes[i]=1 to
00076  *                 exclude source_registry[i]
00077  * @param index Used to return the index of the source with the smallest cost
00078  */
00079 static arm_uc_error_t ARM_UCSM_SourceRegistryGetLowestCost(arm_uc_uri_t* uri,
00080                                                            query_type_t type,
00081                                                            uint8_t* excludes,
00082                                                            uint32_t* index);
00083 
00084 /**
00085  * @brief Find the source of lowest cost and call the corresponding method
00086  *        depending on the type of the request. Retry with source of the next
00087  *        smallest cost if previous sources failed until the source registry
00088  *        is exhausted.
00089  */
00090 static arm_uc_error_t ARM_UCSM_Get(request_t* req);
00091 
00092 /**
00093  * @brief Catch callbacks from sources to enable error handling
00094  */
00095 static void ARM_UCSM_CallbackWrapper(uint32_t event);
00096 
00097 /**
00098  * @brief Retry get due to source being busy
00099  */
00100 static void ARM_UCSM_AsyncRetryGet(uint32_t);
00101 
00102 /**
00103  * @brief Initialise the `Request` struct
00104  */
00105 static arm_uc_error_t ARM_UCSM_RequestStructInit(request_t* request)
00106 {
00107     for (uint32_t i=0; i<MAX_SOURCES; i++)
00108     {
00109         request->excludes[i] = 0;
00110     }
00111 
00112     request->current_source = MAX_SOURCES;
00113     request->uri            = NULL;
00114     request->offset         = 0;
00115     request->type           = QUERY_TYPE_UNKNOWN;
00116     request->buffer         = NULL;
00117 
00118     return (arm_uc_error_t){ SOMA_ERR_NONE };
00119 }
00120 
00121 /**
00122  * @brief Initialise the source_registry array to NULL
00123  */
00124 static arm_uc_error_t ARM_UCSM_SourceRegistryInit(void)
00125 {
00126     for(uint32_t i=0; i<MAX_SOURCES; i++)
00127     {
00128         source_registry[i] = NULL;
00129     }
00130 
00131     return (arm_uc_error_t){ SOMA_ERR_NONE };
00132 }
00133 /**
00134  * @brief Returns the index of the given source in the source array,
00135  *        or MAX_SOURCES if the source is not found
00136  */
00137 static uint32_t ARM_UCSM_GetIndexOfSource(const ARM_UPDATE_SOURCE* source)
00138 {
00139     uint32_t index = MAX_SOURCES;
00140 
00141     for(uint32_t i=0; i<MAX_SOURCES; i++)
00142     {
00143         if(source_registry[i] == source)
00144         {
00145             index = i;
00146             break;
00147         }
00148     }
00149     return index;
00150 }
00151 
00152 /**
00153  * @brief Add pointer to source to the source_registry array
00154  */
00155 static arm_uc_error_t ARM_UCSM_SourceRegistryAdd(const ARM_UPDATE_SOURCE* source)
00156 {
00157     uint8_t added = 0;
00158 
00159     for(uint32_t i=0; i<MAX_SOURCES; i++)
00160     {
00161         if(source_registry[i] == NULL)
00162         {
00163             source_registry[i] = source;
00164             added = 1;
00165             break;
00166         }
00167     }
00168 
00169     if (added == 0) // registry full
00170     {
00171         return (arm_uc_error_t){ SOMA_ERR_SOURCE_REGISTRY_FULL };
00172     }
00173 
00174     return (arm_uc_error_t){ SOMA_ERR_NONE };
00175 }
00176 
00177 /**
00178  * @brief Remove pointer to source from the source_registry array
00179  */
00180 static arm_uc_error_t ARM_UCSM_SourceRegistryRemove(const ARM_UPDATE_SOURCE* source)
00181 {
00182     uint32_t index = ARM_UCSM_GetIndexOfSource(source);
00183 
00184     if (index == MAX_SOURCES) // source not found
00185     {
00186         return (arm_uc_error_t){ SOMA_ERR_SOURCE_NOT_FOUND };
00187     }
00188 
00189     source_registry[index] = NULL;
00190     return (arm_uc_error_t){ SOMA_ERR_NONE };
00191 }
00192 
00193 /**
00194  * @brief return the index of the source with the smallest cost
00195  * @param url Struct containing URL. NULL for default Manifest.
00196  * @param type The type of current request.
00197  * @param excludes Pointer to an array of size MAX_SOURCES to indicate
00198  *                 sources we want to exclude in the search. Set excludes[i]=1 to
00199  *                 exclude source_registry[i]
00200  * @param index Used to return the index of the source with the smalllest cost
00201  */
00202 static arm_uc_error_t ARM_UCSM_SourceRegistryGetLowestCost(arm_uc_uri_t* uri,
00203                                                            query_type_t type,
00204                                                            uint8_t* excludes,
00205                                                            uint32_t* index)
00206 {
00207     uint32_t min_cost = UINT32_MAX;
00208     uint32_t min_cost_index = 0;
00209     arm_uc_error_t retval = (arm_uc_error_t){ SOMA_ERR_NONE };
00210 
00211     UC_SRCE_TRACE("+ARM_UCSM_SourceRegistryGetLowestCost");
00212 
00213     // loop through all sources
00214     for (uint32_t i=0; i<MAX_SOURCES; i++)
00215     {
00216         // if source is NULL or it has been explicitly excluded because of failure before
00217         if (source_registry[i] == NULL || (excludes != NULL && excludes[i] == 1))
00218         {
00219             continue;
00220         }
00221 
00222         ARM_SOURCE_CAPABILITIES cap  = source_registry[i]->GetCapabilities();
00223 
00224         uint32_t cost = UINT32_MAX;
00225         if (uri == NULL && type == QUERY_TYPE_MANIFEST_DEFAULT && cap.manifest_default == 1)
00226         {
00227             retval = source_registry[i]->GetManifestDefaultCost(&cost);
00228         }
00229         else if (uri != NULL && type == QUERY_TYPE_MANIFEST_URL && cap.manifest_url == 1)
00230         {
00231             retval = source_registry[i]->GetManifestURLCost(uri, &cost);
00232         }
00233         else if (uri != NULL && type == QUERY_TYPE_FIRMWARE && cap.firmware == 1)
00234         {
00235             retval = source_registry[i]->GetFirmwareURLCost(uri, &cost);
00236         }
00237         else if (uri != NULL && type == QUERY_TYPE_KEYTABLE && cap.keytable == 1)
00238         {
00239             retval = source_registry[i]->GetKeytableURLCost(uri, &cost);
00240         }
00241 
00242         if (retval.code != SRCE_ERR_NONE) // get cost from source i failed
00243         {
00244             // cost is invalid at this point, hence skip to next iteration
00245             UC_SRCE_TRACE("-ARM_UCSM_SourceRegistryGetLowestCost: invalid cost for %" PRIu32, i);
00246             continue;
00247         }
00248 
00249         // record the cost and i if cost is lower
00250         if (min_cost > cost)
00251         {
00252             min_cost = cost;
00253             min_cost_index = i;
00254         }
00255     }
00256 
00257     if (min_cost == UINT32_MAX)
00258     {
00259         UC_SRCE_TRACE("-ARM_UCSM_SourceRegistryGetLowestCost: Error - No route");
00260         return (arm_uc_error_t){ SOMA_ERR_NO_ROUTE_TO_SOURCE };
00261     }
00262 
00263     *index = min_cost_index;
00264     UC_SRCE_TRACE("-ARM_UCSM_SourceRegistryGetLowestCost: index = %" PRIu32, min_cost_index);
00265     return (arm_uc_error_t){ SOMA_ERR_NONE };
00266 }
00267 
00268 /**
00269  * @brief Find the source of lowest cost and call the corresponding method
00270  *        depending on the type of the request. Retry with source of the next
00271  *        smallest cost if previous sources failed until the source registry
00272  *        is exhausted.
00273  */
00274 static arm_uc_error_t ARM_UCSM_Get(request_t* req)
00275 {
00276     UC_SRCE_TRACE("+ARM_UCSM_Get");
00277     if (req->uri != NULL)
00278     {
00279         UC_SRCE_TRACE("with %" PRIx32 ", host [%s], path [%s], type %" PRIu32,
00280                 req->uri, req->uri->host,req->uri->path, req->type);
00281     }
00282     else
00283     {
00284         UC_SRCE_TRACE("with NULL, type %" PRIu32,
00285                 req->type);
00286     }
00287 
00288     uint32_t index = 0;
00289 
00290     // get the source of lowest cost
00291     arm_uc_error_t retval = ARM_UCSM_SourceRegistryGetLowestCost(req->uri,
00292                                                                  req->type,
00293                                                                  req->excludes,
00294                                                                  &index);
00295     if (retval.code != SOMA_ERR_NONE)
00296     {
00297         UC_SRCE_TRACE("-ARM_UCSM_Get: error retval.code %" PRIu32, retval.code);
00298         return retval;
00299     }
00300 
00301     if ((req->uri == NULL) && (req->type == QUERY_TYPE_MANIFEST_DEFAULT))
00302     {
00303         UC_SRCE_TRACE("calling source %" PRIu32 " GetManifestDefault", index);
00304         retval = source_registry[index]->GetManifestDefault(req->buffer, req->offset);
00305     }
00306     else if ((req->uri != NULL) && (req->type == QUERY_TYPE_MANIFEST_URL))
00307     {
00308         UC_SRCE_TRACE("calling source %" PRIu32 " GetManifestURL with %" PRIx32, index, req->uri);
00309         retval = source_registry[index]->GetManifestURL(req->uri, req->buffer, req->offset);
00310     }
00311     else if ((req->uri != NULL) && (req->type == QUERY_TYPE_FIRMWARE))
00312     {
00313         UC_SRCE_TRACE("calling source %" PRIu32 " GetFirmwareFragment with %" PRIx32, index, req->uri);
00314         retval = source_registry[index]->GetFirmwareFragment(req->uri, req->buffer, req->offset);
00315     }
00316     else if ((req->uri != NULL) && (req->type == QUERY_TYPE_KEYTABLE))
00317     {
00318         UC_SRCE_TRACE("calling source %" PRIu32 " GetKeytableURL with %" PRIx32, index, req->uri);
00319         retval = source_registry[index]->GetKeytableURL(req->uri, req->buffer);
00320     }
00321     else
00322     {
00323         if (req->uri == NULL ) {
00324             UC_SRCE_TRACE("-ARM_UCSM_Get: Error - Invalid parameter (URI == NULL)");
00325         } else {
00326             UC_SRCE_TRACE("-ARM_UCSM_Get: Error - Invalid parameter (unknown request type)");
00327         }
00328         return (arm_uc_error_t){ SOMA_ERR_INVALID_PARAMETER };
00329     }
00330 
00331     if (retval.code == SRCE_ERR_BUSY)
00332     {
00333         UC_SRCE_TRACE("-ARM_UCSM_Get: Error - Busy -> PostCallback AsyncRetryGet");
00334         ARM_UC_PostCallback(&event_cb_storage, ARM_UCSM_AsyncRetryGet, 0);
00335         return (arm_uc_error_t){ SOMA_ERR_NONE };
00336     }
00337     else if (retval.error != ERR_NONE)
00338     {
00339         // failure, try source with the next smallest cost
00340         req->excludes[index] = 1;
00341         UC_SRCE_TRACE("-ARM_UCSM_Get: Error - failure (try source with the next smallest cost)");
00342         return ARM_UCSM_Get(req);
00343     }
00344 
00345     // record the index of source handling the get request currently
00346     req->current_source = index;
00347     UC_SRCE_TRACE("-ARM_UCSM_Get: Using source %" PRIu32, index);
00348 
00349     return (arm_uc_error_t){ SOMA_ERR_NONE };
00350 }
00351 
00352 /**
00353  * @brief If source is busy ARM_UCSM_AsyncRetryGet is registered with
00354           the event queue so it is called again to retry the same source
00355  */
00356 static void ARM_UCSM_AsyncRetryGet(uint32_t unused)
00357 {
00358     (void) unused;
00359 
00360     UC_SRCE_TRACE("+ARM_UCSM_AsyncRetryGet");
00361     arm_uc_error_t retval = ARM_UCSM_Get(&request_in_flight);
00362     if (retval.error != ERR_NONE)
00363     {
00364         ARM_UCSM_RequestStructInit(&request_in_flight);
00365         ARM_UC_PostCallback(&event_cb_storage, event_cb, ARM_UC_SM_EVENT_ERROR);
00366     }
00367     UC_SRCE_TRACE("-ARM_UCSM_AsyncRetryGet");
00368 }
00369 
00370 /**
00371  * @brief Translate source event into source manager event
00372  */
00373 static ARM_UC_SM_Event_t ARM_UCSM_TranslateEvent(uint32_t source_event)
00374 {
00375     ARM_UC_SM_Event_t event = ARM_UC_SM_EVENT_ERROR;
00376 
00377     switch(source_event)
00378     {
00379         case EVENT_NOTIFICATION:
00380             event = ARM_UC_SM_EVENT_NOTIFICATION;
00381             break;
00382         case EVENT_MANIFEST:
00383             event = ARM_UC_SM_EVENT_MANIFEST;
00384             break;
00385         case EVENT_FIRMWARE:
00386             event = ARM_UC_SM_EVENT_FIRMWARE;
00387             break;
00388         case EVENT_KEYTABLE:
00389             event = ARM_UC_SM_EVENT_KEYTABLE;
00390             break;
00391         case EVENT_ERROR:
00392             event = ARM_UC_SM_EVENT_ERROR;
00393             break;
00394         case EVENT_ERROR_BUFFER_SIZE:
00395             event = ARM_UC_SM_EVENT_ERROR_BUFFER_SIZE;
00396             break;
00397     }
00398 
00399     return event;
00400 }
00401 
00402 /**
00403  * @brief Catch callbacks from sources to enable error handling
00404  */
00405 static void ARM_UCSM_CallbackWrapper(uint32_t source_event)
00406 {
00407     UC_SRCE_TRACE("+ARM_UCSM_CallbackWrapper");
00408     UC_SRCE_TRACE("source_event == %" PRIu32, source_event);
00409     ARM_UC_SM_Event_t event = ARM_UCSM_TranslateEvent(source_event);
00410 
00411     if (event == ARM_UC_SM_EVENT_ERROR && request_in_flight.type != QUERY_TYPE_UNKNOWN)
00412     {
00413         UC_SRCE_TRACE("ARM_UCSM_TranslateEvent event error == %" PRIu32, event);
00414         request_in_flight.excludes[request_in_flight.current_source] = 1;
00415         arm_uc_error_t retval = ARM_UCSM_Get(&request_in_flight);
00416         if (retval.code != SOMA_ERR_NONE)
00417         {
00418             UC_SRCE_TRACE("ARM_UCSM_Get() retval.code == %" PRIu32, retval.code);
00419             ARM_UCSM_RequestStructInit(&request_in_flight);
00420             ARM_UC_PostCallback(&event_cb_storage, event_cb, event);
00421         }
00422     }
00423     else
00424     {
00425         UC_SRCE_TRACE("");
00426         ARM_UCSM_RequestStructInit(&request_in_flight);
00427         ARM_UC_PostCallback(&event_cb_storage, event_cb, event);
00428     }
00429     UC_SRCE_TRACE("-ARM_UCSM_CallbackWrapper");
00430 }
00431 
00432 /* ==================================================================== *
00433  * Public API                                                           *
00434  * ==================================================================== */
00435 
00436 /* further documentation of the API can be found in source_manager.h */
00437 
00438 arm_uc_error_t ARM_UCSM_Initialize(ARM_SOURCE_SignalEvent_t callback)
00439 {
00440     // remember the callback
00441     event_cb = callback;
00442 
00443     // init source_registry to NULL
00444     return ARM_UCSM_SourceRegistryInit();
00445 }
00446 
00447 arm_uc_error_t ARM_UCSM_Uninitialize()
00448 {
00449     for (size_t i = 0; i < MAX_SOURCES; i++)
00450     {
00451         if (source_registry[i] != NULL)
00452         {
00453             source_registry[i]->Uninitialize();
00454             source_registry[i] = NULL;
00455         }
00456     }
00457     return (arm_uc_error_t){ERR_NONE};
00458 }
00459 
00460 arm_uc_error_t ARM_UCSM_AddSource(const ARM_UPDATE_SOURCE* source)
00461 {
00462     if (ARM_UCSM_GetIndexOfSource(source) != MAX_SOURCES)
00463     {
00464         // Source already added, don't add again
00465         // TODO: should this return SOMA_ERR_NONE or a new error
00466         // SOMA_ERR_ALREADY_PRESENT?
00467         return (arm_uc_error_t){ SOMA_ERR_NONE };
00468     }
00469     source->Initialize(ARM_UCSM_CallbackWrapper);
00470     return ARM_UCSM_SourceRegistryAdd(source);
00471 }
00472 
00473 arm_uc_error_t ARM_UCSM_RemoveSource(const ARM_UPDATE_SOURCE* source)
00474 {
00475     arm_uc_error_t err = ARM_UCSM_SourceRegistryRemove(source);
00476     if (err.code == SOMA_ERR_NONE)
00477     {
00478         // Call 'uninitialize' only if the source was found (and removed)
00479         source->Uninitialize();
00480     }
00481     return err;
00482 }
00483 
00484 /* All the `Get` APIs map into `ARM_UCSM_Get` */
00485 
00486 arm_uc_error_t ARM_UCSM_GetManifest(arm_uc_buffer_t* buffer, uint32_t offset)
00487 {
00488     UC_SRCE_TRACE("+ARM_UCSM_GetManifest");
00489     ARM_UCSM_RequestStructInit(&request_in_flight);
00490     request_in_flight.buffer = buffer;
00491     request_in_flight.offset = offset;
00492     request_in_flight.type   = QUERY_TYPE_MANIFEST_DEFAULT;
00493 
00494     arm_uc_error_t retval = ARM_UCSM_Get(&request_in_flight);
00495     if (retval.code != SOMA_ERR_NONE)
00496     {
00497         ARM_UCSM_RequestStructInit(&request_in_flight);
00498     }
00499 
00500     UC_SRCE_TRACE("-ARM_UCSM_GetManifest");
00501     return retval;
00502 }
00503 
00504 arm_uc_error_t ARM_UCSM_GetManifestFrom(arm_uc_uri_t* uri,
00505                                         arm_uc_buffer_t* buffer,
00506                                         uint32_t offset)
00507 {
00508     UC_SRCE_TRACE("+ARM_UCSM_GetManifestFrom");
00509     ARM_UCSM_RequestStructInit(&request_in_flight);
00510     request_in_flight.uri    = uri;
00511     request_in_flight.buffer = buffer;
00512     request_in_flight.offset = offset;
00513     request_in_flight.type   = QUERY_TYPE_MANIFEST_URL;
00514 
00515     arm_uc_error_t retval = ARM_UCSM_Get(&request_in_flight);
00516     if (retval.code != SOMA_ERR_NONE)
00517     {
00518         ARM_UCSM_RequestStructInit(&request_in_flight);
00519     }
00520 
00521     UC_SRCE_TRACE("-ARM_UCSM_GetManifestFrom");
00522     return retval;
00523 }
00524 
00525 arm_uc_error_t ARM_UCSM_GetFirmwareFragment(arm_uc_uri_t* uri,
00526                                             arm_uc_buffer_t* buffer,
00527                                             uint32_t offset)
00528 {
00529     UC_SRCE_TRACE("+ARM_UCSM_GetFirmwareFragment");
00530     ARM_UCSM_RequestStructInit(&request_in_flight);
00531     request_in_flight.uri    = uri;
00532     request_in_flight.buffer = buffer;
00533     request_in_flight.offset = offset;
00534     request_in_flight.type   = QUERY_TYPE_FIRMWARE;
00535 
00536     arm_uc_error_t retval = ARM_UCSM_Get(&request_in_flight);
00537     if (retval.code != SOMA_ERR_NONE)
00538     {
00539         ARM_UCSM_RequestStructInit(&request_in_flight);
00540     }
00541 
00542     UC_SRCE_TRACE("-ARM_UCSM_GetFirmwareFragment");
00543     return retval;
00544 }
00545 
00546 arm_uc_error_t ARM_UCSM_GetKeytable(arm_uc_uri_t* uri, arm_uc_buffer_t* buffer)
00547 {
00548     UC_SRCE_TRACE("+ARM_UCSM_GetKeytable");
00549     ARM_UCSM_RequestStructInit(&request_in_flight);
00550     request_in_flight.uri    = uri;
00551     request_in_flight.buffer = buffer;
00552     request_in_flight.type   = QUERY_TYPE_KEYTABLE;
00553 
00554     arm_uc_error_t retval = ARM_UCSM_Get(&request_in_flight);
00555     if (retval.code != SOMA_ERR_NONE)
00556     {
00557         ARM_UCSM_RequestStructInit(&request_in_flight);
00558     }
00559 
00560     UC_SRCE_TRACE("+ARM_UCSM_GetKeytable");
00561     return retval;
00562 }
00563 
00564 ARM_UC_SOURCE_MANAGER_t ARM_UC_SourceManager = {
00565     .Initialize          = ARM_UCSM_Initialize,
00566     .Uninitialize        = ARM_UCSM_Uninitialize,
00567     .AddSource           = ARM_UCSM_AddSource,
00568     .RemoveSource        = ARM_UCSM_RemoveSource,
00569     .GetManifest         = ARM_UCSM_GetManifest,
00570     .GetManifestFrom     = ARM_UCSM_GetManifestFrom,
00571     .GetFirmwareFragment = ARM_UCSM_GetFirmwareFragment,
00572     .GetKeytable         = ARM_UCSM_GetKeytable
00573 };