Mbed Cloud example program for workshop in W27 2018.

Dependencies:   MMA7660 LM75B

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers arm_uc_pal_realtek_rtl8195am.c Source File

arm_uc_pal_realtek_rtl8195am.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 #if defined(TARGET_REALTEK_RTL8195AM)
00020 
00021 #include "update-client-paal/arm_uc_paal_update_api.h"
00022 #include "update-client-pal-flashiap/arm_uc_pal_flashiap_platform.h"
00023 
00024 #include "update-client-common/arm_uc_metadata_header_v2.h"
00025 #include "update-client-common/arm_uc_common.h"
00026 
00027 #include "ota_api.h"
00028 #include "flash_ext.h"
00029 
00030 #define HEADER_SIZE     (OTA_CRC32_OFS + 4)
00031 
00032 typedef enum {
00033     BASE_ADDRESS_RUNNING,
00034     BASE_ADDRESS_SPARE
00035 } base_address_t;
00036 
00037 /**
00038  * Base address, for caching between operations.
00039  */
00040 static size_t arm_uc_base_address = 0;
00041 
00042 /**
00043  * Callback handler.
00044  */
00045 static void (*arm_uc_pal_rtl8195am_callback)(uint32_t) = NULL;
00046 
00047 /**
00048  * @brief      Signal external event handler with NULL pointer check.
00049  *
00050  * @param[in]  event  The event
00051  */
00052 static void arm_uc_pal_rtl8195am_signal_internal(uint32_t event)
00053 {
00054     if (arm_uc_pal_rtl8195am_callback)
00055     {
00056         arm_uc_pal_rtl8195am_callback(event);
00057     }
00058 }
00059 
00060 /**
00061  * @brief      Create header compatible with the RTL8195AM bootloader
00062  *
00063  * @param[in]  details  Update client firmware details struct.
00064  * @param      buffer   Scratch buffer for creating the header.
00065  *
00066  * @return     ERR_NONE on success. ERR_INVALID_PARAMETER on failure.
00067  */
00068 static arm_uc_error_t arm_uc_pal_create_realtek_header(const arm_uc_firmware_details_t* details, arm_uc_buffer_t* buffer)
00069 {
00070     arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER };
00071 
00072     if (details && buffer && buffer->ptr && (buffer->size_max >= HEADER_SIZE))
00073     {
00074         /* set tag */
00075         buffer->ptr[OTA_TAG_OFS    ] =  OTA_TAG_ID        & 0xFF;
00076         buffer->ptr[OTA_TAG_OFS + 1] = (OTA_TAG_ID >>  8) & 0xFF;
00077         buffer->ptr[OTA_TAG_OFS + 2] = (OTA_TAG_ID >> 16) & 0xFF;
00078         buffer->ptr[OTA_TAG_OFS + 3] = (OTA_TAG_ID >> 24) & 0xFF;
00079 
00080         /* set version tag */
00081         buffer->ptr[OTA_VER_OFS    ] =  OTA_VER_ID        & 0xFF;
00082         buffer->ptr[OTA_VER_OFS + 1] = (OTA_VER_ID >>  8) & 0xFF;
00083         buffer->ptr[OTA_VER_OFS + 2] = (OTA_VER_ID >> 16) & 0xFF;
00084         buffer->ptr[OTA_VER_OFS + 3] = (OTA_VER_ID >> 24) & 0xFF;
00085 
00086         /* set timestamp */
00087         buffer->ptr[OTA_EPOCH_OFS    ] =  details->version        & 0xFF;
00088         buffer->ptr[OTA_EPOCH_OFS + 1] = (details->version >>  8) & 0xFF;
00089         buffer->ptr[OTA_EPOCH_OFS + 2] = (details->version >> 16) & 0xFF;
00090         buffer->ptr[OTA_EPOCH_OFS + 3] = (details->version >> 24) & 0xFF;
00091         buffer->ptr[OTA_EPOCH_OFS + 4] = (details->version >> 32) & 0xFF;
00092         buffer->ptr[OTA_EPOCH_OFS + 5] = (details->version >> 40) & 0xFF;
00093         buffer->ptr[OTA_EPOCH_OFS + 6] = (details->version >> 48) & 0xFF;
00094         buffer->ptr[OTA_EPOCH_OFS + 7] = (details->version >> 56) & 0xFF;
00095 
00096         /* set size */
00097         uint32_t size_with_header = details->size + HEADER_SIZE;
00098 
00099         buffer->ptr[OTA_SIZE_OFS    ] =  size_with_header        & 0xFF;
00100         buffer->ptr[OTA_SIZE_OFS + 1] = (size_with_header >>  8) & 0xFF;
00101         buffer->ptr[OTA_SIZE_OFS + 2] = (size_with_header >> 16) & 0xFF;
00102         buffer->ptr[OTA_SIZE_OFS + 3] = (size_with_header >> 24) & 0xFF;
00103 
00104         /* copy hash */
00105         for (size_t index = 0; index < ARM_UC_SHA256_SIZE; index++)
00106         {
00107             buffer->ptr[OTA_HASH_OFS + index] = details->hash[index];
00108         }
00109 
00110         /* copy campaign */
00111         for (size_t index = 0; index < ARM_UC_GUID_SIZE; index++)
00112         {
00113             buffer->ptr[OTA_CAMPAIGN_OFS + index] = details->campaign[index];
00114         }
00115 
00116         /* set buffer size minus CRC */
00117         buffer->size = HEADER_SIZE - 4;
00118 
00119         result.code = ERR_NONE;
00120     }
00121 
00122     return result;
00123 }
00124 
00125 /**
00126  * @brief      Read header for the image located at the base address.
00127  *
00128  * @param[in]  base_address  Start address for firmware slot.
00129  * @param      details       Update client details struct.
00130  *
00131  * @return     ERR_NONE on success, ERR_INVALID_PARAMETER on failure.
00132  */
00133 static arm_uc_error_t arm_uc_pal_get_realtek_header(uint32_t base_address,
00134                                                     arm_uc_firmware_details_t* details)
00135 {
00136     arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER };
00137 
00138     if (details)
00139     {
00140         uint8_t buffer[HEADER_SIZE] = { 0 };
00141 
00142         int rc = arm_uc_flashiap_read(buffer, base_address, sizeof(buffer));
00143 
00144         if (rc == 0)
00145         {
00146 #if 0
00147             printf("debug: \r\n");
00148             for (size_t index = 0; index < sizeof(buffer); index++)
00149             {
00150                 printf("%02X", buffer[index]);
00151             }
00152             printf("\r\n");
00153 #endif
00154 
00155             /* parse tag */
00156             uint32_t tag = buffer[OTA_TAG_OFS + 3];
00157             tag = (tag << 8) | buffer[OTA_TAG_OFS + 2];
00158             tag = (tag << 8) | buffer[OTA_TAG_OFS + 1];
00159             tag = (tag << 8) | buffer[OTA_TAG_OFS + 0];
00160 
00161             /* parse version tag */
00162             uint32_t version_tag = buffer[OTA_VER_OFS + 3];
00163             version_tag = (version_tag << 8) | buffer[OTA_VER_OFS + 2];
00164             version_tag = (version_tag << 8) | buffer[OTA_VER_OFS + 1];
00165             version_tag = (version_tag << 8) | buffer[OTA_VER_OFS + 0];
00166 
00167             UC_PAAL_TRACE("tag: %" PRIX32, tag);
00168             UC_PAAL_TRACE("version_tag: %" PRIX32, version_tag);
00169 
00170             /* check tags */
00171             if ((tag == OTA_TAG_ID) && (version_tag == OTA_VER_ID))
00172             {
00173                 /* parse CRC */
00174                 uint32_t crc_header = buffer[OTA_CRC32_OFS + 3];
00175                 crc_header = (crc_header << 8) | buffer[OTA_CRC32_OFS + 2];
00176                 crc_header = (crc_header << 8) | buffer[OTA_CRC32_OFS + 1];
00177                 crc_header = (crc_header << 8) | buffer[OTA_CRC32_OFS + 0];
00178 
00179                 /* calculate crc */
00180                 uint32_t crc_calculated = arm_uc_crc32(buffer, OTA_CRC32_OFS);
00181 
00182                 UC_PAAL_TRACE("CRC header:     %" PRIX32, crc_header);
00183                 UC_PAAL_TRACE("CRC calculated: %" PRIX32, crc_calculated);
00184 
00185                 /* check crc before proceeding */
00186                 if (crc_header == crc_calculated)
00187                 {
00188                     /* parse size */
00189                     uint32_t size = buffer[OTA_SIZE_OFS + 3];
00190                     size = (size << 8) | buffer[OTA_SIZE_OFS + 2];
00191                     size = (size << 8) | buffer[OTA_SIZE_OFS + 1];
00192                     size = (size << 8) | buffer[OTA_SIZE_OFS + 0];
00193 
00194                     /* parse version */
00195                     uint64_t version = buffer[OTA_EPOCH_OFS + 7];
00196                     version = (version << 8) | buffer[OTA_EPOCH_OFS + 6];
00197                     version = (version << 8) | buffer[OTA_EPOCH_OFS + 5];
00198                     version = (version << 8) | buffer[OTA_EPOCH_OFS + 4];
00199                     version = (version << 8) | buffer[OTA_EPOCH_OFS + 3];
00200                     version = (version << 8) | buffer[OTA_EPOCH_OFS + 2];
00201                     version = (version << 8) | buffer[OTA_EPOCH_OFS + 1];
00202                     version = (version << 8) | buffer[OTA_EPOCH_OFS + 0];
00203 
00204                     /* copy hash */
00205                     for (size_t index = 0; index < ARM_UC_SHA256_SIZE; index++)
00206                     {
00207                         details->hash[index] = buffer[OTA_HASH_OFS + index];
00208                     }
00209 
00210                     details->size = size - HEADER_SIZE;
00211                     details->version = version;
00212 
00213                     UC_PAAL_TRACE("size: %" PRIu64, details->size);
00214                     UC_PAAL_TRACE("version: %" PRIu64, details->version);
00215 
00216 #if 0
00217                     printf("hash: ");
00218                     for (size_t index = 0; index < ARM_UC_SHA256_SIZE; index++)
00219                     {
00220                         printf("%02X", details->hash[index]);
00221                     }
00222                     printf("\r\n");
00223 #endif
00224 
00225                     result.code = ERR_NONE;
00226                 }
00227                 else
00228                 {
00229                     UC_PAAL_ERR_MSG("header crc check failed");
00230                 }
00231             }
00232             else
00233             {
00234                 UC_PAAL_ERR_MSG("invalid header");
00235             }
00236         }
00237         else
00238         {
00239             UC_PAAL_ERR_MSG("error reading from flash");
00240         }
00241     }
00242 
00243     return result;
00244 }
00245 
00246 /**
00247  * @brief      Find base address of either running or spare firmare slot.
00248  *
00249  * @param[in]  find  Enum specifying what to find (running or spare slot).
00250  *
00251  * @return     Base address.
00252  */
00253 static uint32_t arm_uc_pal_find_base_address(base_address_t find)
00254 {
00255     uint32_t base_address = 0;
00256 
00257     arm_uc_firmware_details_t slot_0 = { 0 };
00258     arm_uc_firmware_details_t slot_1 = { 0 };
00259 
00260     /* read header from both slots */
00261     arm_uc_error_t result_0 = arm_uc_pal_get_realtek_header(OTA_REGION1_BASE, &slot_0);
00262     arm_uc_error_t result_1 = arm_uc_pal_get_realtek_header(OTA_REGION2_BASE, &slot_1);
00263 
00264     /* both headers are valid */
00265     if ((result_0.error == ERR_NONE) && (result_1.error == ERR_NONE))
00266     {
00267         /* running firmware has the highest version number */
00268         if (find == BASE_ADDRESS_RUNNING)
00269         {
00270             base_address = (slot_0.version >= slot_1.version) ? OTA_REGION1_BASE : OTA_REGION2_BASE;
00271         }
00272         /* spare firmware has the lowest version number */
00273         else
00274         {
00275             /* same test, swap result */
00276             base_address = (slot_0.version >= slot_1.version) ? OTA_REGION2_BASE : OTA_REGION1_BASE;
00277         }
00278     }
00279     /* only slot0 has a valid header */
00280     else if (result_0.error == ERR_NONE)
00281     {
00282         if (find == BASE_ADDRESS_RUNNING)
00283         {
00284             /* only valid header must be the running one */
00285             base_address = OTA_REGION1_BASE;
00286         }
00287         else
00288         {
00289             /* slot with invalid header can be used as spare */
00290             base_address = OTA_REGION2_BASE;
00291         }
00292     }
00293     /* only slot1 has a valid header */
00294     else if (result_1.error == ERR_NONE)
00295     {
00296         if (find == BASE_ADDRESS_RUNNING)
00297         {
00298             /* only valid header must be the running one */
00299             base_address = OTA_REGION2_BASE;
00300         }
00301         else
00302         {
00303             /* slot with invalid header can be used as spare */
00304             base_address = OTA_REGION1_BASE;
00305         }
00306     }
00307 
00308     /* if both headers are invalid return 0 */
00309 
00310     return base_address;
00311 }
00312 
00313 /*****************************************************************************/
00314 
00315 arm_uc_error_t ARM_UC_PAL_RTL8195AM_Initialize(void (*callback)(uint32_t))
00316 {
00317     arm_uc_error_t result = { .code = ERR_NONE };
00318 
00319     arm_uc_pal_rtl8195am_callback = callback;
00320 
00321     return result;
00322 }
00323 
00324 /**
00325  * @brief Get maximum number of supported storage locations.
00326  *
00327  * @return Number of storage locations.
00328  */
00329 uint32_t ARM_UC_PAL_RTL8195AM_GetMaxID(void)
00330 {
00331     return 2;
00332 }
00333 
00334 /**
00335  * @brief Prepare the storage layer for a new firmware image.
00336  * @details The storage location is set up to receive an image with
00337  *          the details passed in the details struct.
00338  *
00339  * @param location Storage location ID.
00340  * @param details Pointer to a struct with firmware details.
00341  * @param buffer Temporary buffer for formatting and storing metadata.
00342  * @return Returns ERR_NONE on accept, and signals the event handler with
00343  *         either DONE or ERROR when complete.
00344  *         Returns ERR_INVALID_PARAMETER on reject, and no signal is sent.
00345  */
00346 arm_uc_error_t ARM_UC_PAL_RTL8195AM_Prepare(uint32_t location,
00347                                             const arm_uc_firmware_details_t* details,
00348                                             arm_uc_buffer_t* buffer)
00349 {
00350     arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER };
00351 
00352     if (details && buffer && buffer->ptr)
00353     {
00354         UC_PAAL_TRACE("Prepare: %" PRIX32 " %" PRIX64 " %" PRIu64,
00355                       location,
00356                       details->size,
00357                       details->version);
00358 
00359         /* find location for the spare slot */
00360         arm_uc_base_address = arm_uc_pal_find_base_address(BASE_ADDRESS_SPARE);
00361 
00362         UC_PAAL_TRACE("spare base: %" PRIX32, arm_uc_base_address);
00363 
00364         /* check that the firmware can fit the spare slot */
00365         if (((arm_uc_base_address == OTA_REGION1_BASE) && (details->size < OTA_REGION1_SIZE)) ||
00366             ((arm_uc_base_address == OTA_REGION2_BASE) && (details->size < OTA_REGION2_SIZE)))
00367         {
00368             /* encode firmware details in buffer */
00369             result  = arm_uc_pal_create_realtek_header(details, buffer);
00370 
00371             /* make space for new firmware */
00372             if (result.error == ERR_NONE)
00373             {
00374                 /* find end address */
00375                 uint32_t end_address = arm_uc_base_address + HEADER_SIZE + details->size;
00376 
00377                 /* erase */
00378                 uint32_t erase_address = arm_uc_base_address;
00379 
00380                 while (erase_address < end_address)
00381                 {
00382                     uint32_t sector_size = arm_uc_flashiap_get_sector_size(erase_address);
00383 
00384                     int status = arm_uc_flashiap_erase(erase_address, sector_size);
00385 
00386                     UC_PAAL_TRACE("erase: %" PRIX32 " %" PRIX32 " %d",
00387                                   erase_address,
00388                                   sector_size,
00389                                   status);
00390 
00391                     if (status == 0)
00392                     {
00393                         erase_address += sector_size;
00394                     }
00395                     else
00396                     {
00397                         result.code = ERR_INVALID_PARAMETER;
00398                         break;
00399                     }
00400                 }
00401 
00402                 /* write header */
00403                 if (result.error == ERR_NONE)
00404                 {
00405                     UC_PAAL_TRACE("program: %u %" PRIu32,
00406                                   arm_uc_base_address,
00407                                   buffer->size);
00408 
00409                     /* set default return code */
00410                     result.code = ERR_NONE;
00411 
00412                     /* write header without CRC */
00413                     int status = arm_uc_flashiap_program(buffer->ptr,
00414                                                          arm_uc_base_address,
00415                                                          buffer->size);
00416 
00417                     if (status != 0)
00418                     {
00419                         /* set return code */
00420                         result.code = ERR_INVALID_PARAMETER;
00421                     }
00422 
00423                     if (result.error == ERR_NONE)
00424                     {
00425                         /* signal done */
00426                         arm_uc_pal_rtl8195am_signal_internal(ARM_UC_PAAL_EVENT_PREPARE_DONE);
00427                     }
00428                     else
00429                     {
00430                         UC_PAAL_ERR_MSG("flash program failed");
00431                     }
00432                 }
00433                 else
00434                 {
00435                     UC_PAAL_ERR_MSG("flash erase failed");
00436                 }
00437             }
00438             else
00439             {
00440                 UC_PAAL_ERR_MSG("create header failed");
00441             }
00442         }
00443         else
00444         {
00445             UC_PAAL_ERR_MSG("firmware larger than slot");
00446         }
00447     }
00448 
00449     return result;
00450 }
00451 
00452 /**
00453  * @brief Write a fragment to the indicated storage location.
00454  * @details The storage location must have been allocated using the Prepare
00455  *          call. The call is expected to write the entire fragment before
00456  *          signaling completion.
00457  *
00458  * @param location Storage location ID.
00459  * @param offset Offset in bytes to where the fragment should be written.
00460  * @param buffer Pointer to buffer struct with fragment.
00461  * @return Returns ERR_NONE on accept, and signals the event handler with
00462  *         either DONE or ERROR when complete.
00463  *         Returns ERR_INVALID_PARAMETER on reject, and no signal is sent.
00464  */
00465 arm_uc_error_t ARM_UC_PAL_RTL8195AM_Write(uint32_t location,
00466                                           uint32_t offset,
00467                                           const arm_uc_buffer_t* buffer)
00468 {
00469     arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER };
00470 
00471     if (buffer && buffer->ptr)
00472     {
00473         /* find location address */
00474         uint32_t physical_address = arm_uc_base_address + HEADER_SIZE + offset;
00475 
00476         UC_PAAL_TRACE("Write: %p %" PRIX32 " %" PRIX32 " %" PRIX32,
00477                  buffer->ptr,
00478                  buffer->size,
00479                  offset,
00480                  physical_address);
00481 
00482         /* set default return code */
00483         result.code = ERR_NONE;
00484 
00485         for (size_t index = 0; index < buffer->size; )
00486         {
00487             /* write aligned */
00488             size_t modulo = (physical_address + index) % FLASH_PAGE_SIZE;
00489             size_t remaining = buffer->size - index;
00490             size_t write_size = 0;
00491 
00492             /* fill remaining flash page */
00493             if (modulo > 0)
00494             {
00495                 write_size = modulo;
00496             }
00497             /* write last page */
00498             else if (remaining < FLASH_PAGE_SIZE)
00499             {
00500                 write_size = remaining;
00501             }
00502             /* write full page */
00503             else
00504             {
00505                 write_size = FLASH_PAGE_SIZE;
00506             }
00507 
00508             int status = arm_uc_flashiap_program(&buffer->ptr[index],
00509                                                  physical_address + index,
00510                                                  write_size);
00511 
00512             if (status != 0)
00513             {
00514                 /* set return code */
00515                 result.code = ERR_INVALID_PARAMETER;
00516                 break;
00517             }
00518 
00519             index += write_size;
00520         }
00521 
00522         if (result.error == ERR_NONE)
00523         {
00524             /* signal done */
00525             arm_uc_pal_rtl8195am_signal_internal(ARM_UC_PAAL_EVENT_WRITE_DONE);
00526         }
00527         else
00528         {
00529             UC_PAAL_ERR_MSG("flash program failed");
00530         }
00531     }
00532 
00533     return result;
00534 }
00535 
00536 /**
00537  * @brief Close storage location for writing and flush pending data.
00538  *
00539  * @param location Storage location ID.
00540  * @return Returns ERR_NONE on accept, and signals the event handler with
00541  *         either DONE or ERROR when complete.
00542  *         Returns ERR_INVALID_PARAMETER on reject, and no signal is sent.
00543  */
00544 arm_uc_error_t ARM_UC_PAL_RTL8195AM_Finalize(uint32_t location)
00545 {
00546     arm_uc_error_t result = { .code = ERR_NONE };
00547 
00548     UC_PAAL_TRACE("Finalize");
00549 
00550     arm_uc_pal_rtl8195am_signal_internal(ARM_UC_PAAL_EVENT_FINALIZE_DONE);
00551 
00552     return result;
00553 }
00554 
00555 /**
00556  * @brief Read a fragment from the indicated storage location.
00557  * @details The function will read until the buffer is full or the end of
00558  *          the storage location has been reached. The actual amount of
00559  *          bytes read is set in the buffer struct.
00560  *
00561  * @param location Storage location ID.
00562  * @param offset Offset in bytes to read from.
00563  * @param buffer Pointer to buffer struct to store fragment.
00564  * @return Returns ERR_NONE on accept, and signals the event handler with
00565  *         either DONE or ERROR when complete.
00566  *         Returns ERR_INVALID_PARAMETER on reject, and no signal is sent.
00567  */
00568 arm_uc_error_t ARM_UC_PAL_RTL8195AM_Read(uint32_t location,
00569                                          uint32_t offset,
00570                                          arm_uc_buffer_t* buffer)
00571 {
00572     arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER };
00573 
00574     if (buffer && buffer->ptr)
00575     {
00576         /* find the base address for the spare slot if not already set */
00577         if (arm_uc_base_address == 0)
00578         {
00579             arm_uc_base_address = arm_uc_pal_find_base_address(BASE_ADDRESS_SPARE);
00580         }
00581 
00582         /* calculate actual physical address */
00583         uint32_t physical_address = arm_uc_base_address + HEADER_SIZE + offset;
00584 
00585         UC_PAAL_TRACE("Read: %" PRIX32 " %" PRIX32 " %" PRIX32,
00586                       physical_address,
00587                       offset,
00588                       buffer->size_max);
00589 
00590         uint32_t read_size = buffer->size_max;
00591 
00592         int status = arm_uc_flashiap_read(buffer->ptr, physical_address, read_size);
00593 
00594         if (status == 0)
00595         {
00596             /* set buffer size */
00597             buffer->size = read_size;
00598 
00599             /* set return code */
00600             result.code = ERR_NONE;
00601 
00602             /* signal done */
00603             arm_uc_pal_rtl8195am_signal_internal(ARM_UC_PAAL_EVENT_READ_DONE);
00604         }
00605         else
00606         {
00607             UC_PAAL_ERR_MSG("flash read failed");
00608         }
00609     }
00610 
00611     return result;
00612 }
00613 
00614 /**
00615  * @brief Set the firmware image in the slot to be the new active image.
00616  * @details This call is responsible for initiating the process for
00617  *          applying a new/different image. Depending on the platform this
00618  *          could be:
00619  *           * An empty call, if the installer can deduce which slot to
00620  *             choose from based on the firmware details.
00621  *           * Setting a flag to indicate which slot to use next.
00622  *           * Decompressing/decrypting/installing the firmware image on
00623  *             top of another.
00624  *
00625  * @param location Storage location ID.
00626  * @return Returns ERR_NONE on accept, and signals the event handler with
00627  *         either DONE or ERROR when complete.
00628  *         Returns ERR_INVALID_PARAMETER on reject, and no signal is sent.
00629  */
00630 arm_uc_error_t ARM_UC_PAL_RTL8195AM_Activate(uint32_t location)
00631 {
00632     arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER };
00633 
00634     UC_PAAL_TRACE("Activate");
00635 
00636     uint8_t buffer[HEADER_SIZE] = { 0 };
00637 
00638     int status = arm_uc_flashiap_read(buffer, arm_uc_base_address, sizeof(buffer));
00639 
00640     if (status == 0)
00641     {
00642         /* calculate CRC */
00643         uint32_t crc = arm_uc_crc32(buffer, OTA_CRC32_OFS);
00644 
00645         buffer[0] =  crc        & 0xFF;
00646         buffer[1] = (crc >>  8) & 0xFF;
00647         buffer[2] = (crc >> 16) & 0xFF;
00648         buffer[3] = (crc >> 24) & 0xFF;
00649 
00650         /* set crc in header to signal the bootloader that the image is ready */
00651         status = arm_uc_flashiap_program(buffer, arm_uc_base_address + OTA_CRC32_OFS, 4);
00652 
00653         if (status == 0)
00654         {
00655             /* set return code */
00656             result.code = ERR_NONE;
00657 
00658             /* signal done */
00659             arm_uc_pal_rtl8195am_signal_internal(ARM_UC_PAAL_EVENT_ACTIVATE_DONE);
00660         }
00661     }
00662 
00663     return result;
00664 }
00665 
00666 /**
00667  * @brief Get firmware details for the firmware image in the slot passed.
00668  * @details This call populates the passed details struct with information
00669  *          about the firmware image in the slot passed. Only the fields
00670  *          marked as supported in the capabilities bitmap will have valid
00671  *          values.
00672  *
00673  * @param details Pointer to firmware details struct to be populated.
00674  * @return Returns ERR_NONE on accept, and signals the event handler with
00675  *         either DONE or ERROR when complete.
00676  *         Returns ERR_INVALID_PARAMETER on reject, and no signal is sent.
00677  */
00678 arm_uc_error_t ARM_UC_PAL_RTL8195AM_GetFirmwareDetails(
00679                                         uint32_t location,
00680                                         arm_uc_firmware_details_t* details)
00681 {
00682     arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER };
00683 
00684     /* this function is only used by the mbed Bootloader */
00685 
00686     return result;
00687 }
00688 
00689 /*****************************************************************************/
00690 
00691 arm_uc_error_t ARM_UC_PAL_RTL8195AM_GetActiveDetails(arm_uc_firmware_details_t* details)
00692 {
00693     arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER };
00694 
00695     if (details)
00696     {
00697         UC_PAAL_TRACE("GetActiveDetails");
00698 
00699         /* find running slot */
00700         uint32_t base_address = arm_uc_pal_find_base_address(BASE_ADDRESS_RUNNING);
00701 
00702         UC_PAAL_TRACE("active base: %" PRIX32, base_address);
00703 
00704         result = arm_uc_pal_get_realtek_header(base_address, details);
00705 
00706         /* signal event if operation was successful */
00707         if (result.error == ERR_NONE)
00708         {
00709             arm_uc_pal_rtl8195am_signal_internal(ARM_UC_PAAL_EVENT_GET_ACTIVE_FIRMWARE_DETAILS_DONE);
00710         }
00711     }
00712 
00713     return result;
00714 }
00715 
00716 arm_uc_error_t ARM_UC_PAL_RTL8195AM_GetInstallerDetails(arm_uc_installer_details_t* details)
00717 {
00718     arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER };
00719 
00720     if (details)
00721     {
00722         /* reset installer details struct */
00723         memset(&details->arm_hash, 0, ARM_UC_SHA256_SIZE);
00724         memset(&details->oem_hash, 0, ARM_UC_SHA256_SIZE);
00725         details->layout = 0;
00726 
00727         /* the magic tag identifies the bootloader it is compatible with */
00728         details->oem_hash[0] = (OTA_TAG_ID >> 24) & 0xFF;
00729         details->oem_hash[1] = (OTA_TAG_ID >> 16) & 0xFF;
00730         details->oem_hash[2] = (OTA_TAG_ID >>  8) & 0xFF;
00731         details->oem_hash[3] =  OTA_TAG_ID        & 0xFF;
00732 
00733         details->oem_hash[4] = (OTA_VER_ID >> 24) & 0xFF;
00734         details->oem_hash[5] = (OTA_VER_ID >> 16) & 0xFF;
00735         details->oem_hash[6] = (OTA_VER_ID >>  8) & 0xFF;
00736         details->oem_hash[7] =  OTA_VER_ID        & 0xFF;
00737 
00738         result.code = ERR_NONE;
00739 
00740         arm_uc_pal_rtl8195am_signal_internal(ARM_UC_PAAL_EVENT_GET_INSTALLER_DETAILS_DONE);
00741     }
00742 
00743     return result;
00744 }
00745 
00746 ARM_UC_PAAL_UPDATE_CAPABILITIES ARM_UC_PAL_RTL8195AM_GetCapabilities(void)
00747 {
00748     ARM_UC_PAAL_UPDATE_CAPABILITIES result = {
00749         .installer_arm_hash = 0,
00750         .installer_oem_hash = 0,
00751         .installer_layout   = 0,
00752         .firmware_hash      = 1,
00753         .firmware_hmac      = 0,
00754         .firmware_campaign  = 0,
00755         .firmware_version   = 1,
00756         .firmware_size      = 1
00757     };
00758 
00759     return result;
00760 }
00761 
00762 const ARM_UC_PAAL_UPDATE ARM_UCP_REALTEK_RTL8195AM =
00763 {
00764     .Initialize                 = ARM_UC_PAL_RTL8195AM_Initialize,
00765     .GetCapabilities            = ARM_UC_PAL_RTL8195AM_GetCapabilities,
00766     .GetMaxID                   = ARM_UC_PAL_RTL8195AM_GetMaxID,
00767     .Prepare                    = ARM_UC_PAL_RTL8195AM_Prepare,
00768     .Write                      = ARM_UC_PAL_RTL8195AM_Write,
00769     .Finalize                   = ARM_UC_PAL_RTL8195AM_Finalize,
00770     .Read                       = ARM_UC_PAL_RTL8195AM_Read,
00771     .Activate                   = ARM_UC_PAL_RTL8195AM_Activate,
00772     .GetActiveFirmwareDetails   = ARM_UC_PAL_RTL8195AM_GetActiveDetails,
00773     .GetFirmwareDetails         = ARM_UC_PAL_RTL8195AM_GetFirmwareDetails,
00774     .GetInstallerDetails        = ARM_UC_PAL_RTL8195AM_GetInstallerDetails
00775 };
00776 
00777 #endif