Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
mbed-cloud-client/update-client-hub/modules/pal-target-specific/source/arm_uc_pal_realtek_rtl8195am.c@0:276e7a263c35, 2018-07-02 (annotated)
- Committer:
- MACRUM
- Date:
- Mon Jul 02 06:30:39 2018 +0000
- Revision:
- 0:276e7a263c35
Initial commit
Who changed what in which revision?
| User | Revision | Line number | New contents of line |
|---|---|---|---|
| MACRUM | 0:276e7a263c35 | 1 | // ---------------------------------------------------------------------------- |
| MACRUM | 0:276e7a263c35 | 2 | // Copyright 2016-2017 ARM Ltd. |
| MACRUM | 0:276e7a263c35 | 3 | // |
| MACRUM | 0:276e7a263c35 | 4 | // SPDX-License-Identifier: Apache-2.0 |
| MACRUM | 0:276e7a263c35 | 5 | // |
| MACRUM | 0:276e7a263c35 | 6 | // Licensed under the Apache License, Version 2.0 (the "License"); |
| MACRUM | 0:276e7a263c35 | 7 | // you may not use this file except in compliance with the License. |
| MACRUM | 0:276e7a263c35 | 8 | // You may obtain a copy of the License at |
| MACRUM | 0:276e7a263c35 | 9 | // |
| MACRUM | 0:276e7a263c35 | 10 | // http://www.apache.org/licenses/LICENSE-2.0 |
| MACRUM | 0:276e7a263c35 | 11 | // |
| MACRUM | 0:276e7a263c35 | 12 | // Unless required by applicable law or agreed to in writing, software |
| MACRUM | 0:276e7a263c35 | 13 | // distributed under the License is distributed on an "AS IS" BASIS, |
| MACRUM | 0:276e7a263c35 | 14 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| MACRUM | 0:276e7a263c35 | 15 | // See the License for the specific language governing permissions and |
| MACRUM | 0:276e7a263c35 | 16 | // limitations under the License. |
| MACRUM | 0:276e7a263c35 | 17 | // ---------------------------------------------------------------------------- |
| MACRUM | 0:276e7a263c35 | 18 | |
| MACRUM | 0:276e7a263c35 | 19 | #if defined(TARGET_REALTEK_RTL8195AM) |
| MACRUM | 0:276e7a263c35 | 20 | |
| MACRUM | 0:276e7a263c35 | 21 | #include "update-client-paal/arm_uc_paal_update_api.h" |
| MACRUM | 0:276e7a263c35 | 22 | #include "update-client-pal-flashiap/arm_uc_pal_flashiap_platform.h" |
| MACRUM | 0:276e7a263c35 | 23 | |
| MACRUM | 0:276e7a263c35 | 24 | #include "update-client-common/arm_uc_metadata_header_v2.h" |
| MACRUM | 0:276e7a263c35 | 25 | #include "update-client-common/arm_uc_common.h" |
| MACRUM | 0:276e7a263c35 | 26 | |
| MACRUM | 0:276e7a263c35 | 27 | #include "ota_api.h" |
| MACRUM | 0:276e7a263c35 | 28 | #include "flash_ext.h" |
| MACRUM | 0:276e7a263c35 | 29 | |
| MACRUM | 0:276e7a263c35 | 30 | #define HEADER_SIZE (OTA_CRC32_OFS + 4) |
| MACRUM | 0:276e7a263c35 | 31 | |
| MACRUM | 0:276e7a263c35 | 32 | typedef enum { |
| MACRUM | 0:276e7a263c35 | 33 | BASE_ADDRESS_RUNNING, |
| MACRUM | 0:276e7a263c35 | 34 | BASE_ADDRESS_SPARE |
| MACRUM | 0:276e7a263c35 | 35 | } base_address_t; |
| MACRUM | 0:276e7a263c35 | 36 | |
| MACRUM | 0:276e7a263c35 | 37 | /** |
| MACRUM | 0:276e7a263c35 | 38 | * Base address, for caching between operations. |
| MACRUM | 0:276e7a263c35 | 39 | */ |
| MACRUM | 0:276e7a263c35 | 40 | static size_t arm_uc_base_address = 0; |
| MACRUM | 0:276e7a263c35 | 41 | |
| MACRUM | 0:276e7a263c35 | 42 | /** |
| MACRUM | 0:276e7a263c35 | 43 | * Callback handler. |
| MACRUM | 0:276e7a263c35 | 44 | */ |
| MACRUM | 0:276e7a263c35 | 45 | static void (*arm_uc_pal_rtl8195am_callback)(uint32_t) = NULL; |
| MACRUM | 0:276e7a263c35 | 46 | |
| MACRUM | 0:276e7a263c35 | 47 | /** |
| MACRUM | 0:276e7a263c35 | 48 | * @brief Signal external event handler with NULL pointer check. |
| MACRUM | 0:276e7a263c35 | 49 | * |
| MACRUM | 0:276e7a263c35 | 50 | * @param[in] event The event |
| MACRUM | 0:276e7a263c35 | 51 | */ |
| MACRUM | 0:276e7a263c35 | 52 | static void arm_uc_pal_rtl8195am_signal_internal(uint32_t event) |
| MACRUM | 0:276e7a263c35 | 53 | { |
| MACRUM | 0:276e7a263c35 | 54 | if (arm_uc_pal_rtl8195am_callback) |
| MACRUM | 0:276e7a263c35 | 55 | { |
| MACRUM | 0:276e7a263c35 | 56 | arm_uc_pal_rtl8195am_callback(event); |
| MACRUM | 0:276e7a263c35 | 57 | } |
| MACRUM | 0:276e7a263c35 | 58 | } |
| MACRUM | 0:276e7a263c35 | 59 | |
| MACRUM | 0:276e7a263c35 | 60 | /** |
| MACRUM | 0:276e7a263c35 | 61 | * @brief Create header compatible with the RTL8195AM bootloader |
| MACRUM | 0:276e7a263c35 | 62 | * |
| MACRUM | 0:276e7a263c35 | 63 | * @param[in] details Update client firmware details struct. |
| MACRUM | 0:276e7a263c35 | 64 | * @param buffer Scratch buffer for creating the header. |
| MACRUM | 0:276e7a263c35 | 65 | * |
| MACRUM | 0:276e7a263c35 | 66 | * @return ERR_NONE on success. ERR_INVALID_PARAMETER on failure. |
| MACRUM | 0:276e7a263c35 | 67 | */ |
| MACRUM | 0:276e7a263c35 | 68 | static arm_uc_error_t arm_uc_pal_create_realtek_header(const arm_uc_firmware_details_t* details, arm_uc_buffer_t* buffer) |
| MACRUM | 0:276e7a263c35 | 69 | { |
| MACRUM | 0:276e7a263c35 | 70 | arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER }; |
| MACRUM | 0:276e7a263c35 | 71 | |
| MACRUM | 0:276e7a263c35 | 72 | if (details && buffer && buffer->ptr && (buffer->size_max >= HEADER_SIZE)) |
| MACRUM | 0:276e7a263c35 | 73 | { |
| MACRUM | 0:276e7a263c35 | 74 | /* set tag */ |
| MACRUM | 0:276e7a263c35 | 75 | buffer->ptr[OTA_TAG_OFS ] = OTA_TAG_ID & 0xFF; |
| MACRUM | 0:276e7a263c35 | 76 | buffer->ptr[OTA_TAG_OFS + 1] = (OTA_TAG_ID >> 8) & 0xFF; |
| MACRUM | 0:276e7a263c35 | 77 | buffer->ptr[OTA_TAG_OFS + 2] = (OTA_TAG_ID >> 16) & 0xFF; |
| MACRUM | 0:276e7a263c35 | 78 | buffer->ptr[OTA_TAG_OFS + 3] = (OTA_TAG_ID >> 24) & 0xFF; |
| MACRUM | 0:276e7a263c35 | 79 | |
| MACRUM | 0:276e7a263c35 | 80 | /* set version tag */ |
| MACRUM | 0:276e7a263c35 | 81 | buffer->ptr[OTA_VER_OFS ] = OTA_VER_ID & 0xFF; |
| MACRUM | 0:276e7a263c35 | 82 | buffer->ptr[OTA_VER_OFS + 1] = (OTA_VER_ID >> 8) & 0xFF; |
| MACRUM | 0:276e7a263c35 | 83 | buffer->ptr[OTA_VER_OFS + 2] = (OTA_VER_ID >> 16) & 0xFF; |
| MACRUM | 0:276e7a263c35 | 84 | buffer->ptr[OTA_VER_OFS + 3] = (OTA_VER_ID >> 24) & 0xFF; |
| MACRUM | 0:276e7a263c35 | 85 | |
| MACRUM | 0:276e7a263c35 | 86 | /* set timestamp */ |
| MACRUM | 0:276e7a263c35 | 87 | buffer->ptr[OTA_EPOCH_OFS ] = details->version & 0xFF; |
| MACRUM | 0:276e7a263c35 | 88 | buffer->ptr[OTA_EPOCH_OFS + 1] = (details->version >> 8) & 0xFF; |
| MACRUM | 0:276e7a263c35 | 89 | buffer->ptr[OTA_EPOCH_OFS + 2] = (details->version >> 16) & 0xFF; |
| MACRUM | 0:276e7a263c35 | 90 | buffer->ptr[OTA_EPOCH_OFS + 3] = (details->version >> 24) & 0xFF; |
| MACRUM | 0:276e7a263c35 | 91 | buffer->ptr[OTA_EPOCH_OFS + 4] = (details->version >> 32) & 0xFF; |
| MACRUM | 0:276e7a263c35 | 92 | buffer->ptr[OTA_EPOCH_OFS + 5] = (details->version >> 40) & 0xFF; |
| MACRUM | 0:276e7a263c35 | 93 | buffer->ptr[OTA_EPOCH_OFS + 6] = (details->version >> 48) & 0xFF; |
| MACRUM | 0:276e7a263c35 | 94 | buffer->ptr[OTA_EPOCH_OFS + 7] = (details->version >> 56) & 0xFF; |
| MACRUM | 0:276e7a263c35 | 95 | |
| MACRUM | 0:276e7a263c35 | 96 | /* set size */ |
| MACRUM | 0:276e7a263c35 | 97 | uint32_t size_with_header = details->size + HEADER_SIZE; |
| MACRUM | 0:276e7a263c35 | 98 | |
| MACRUM | 0:276e7a263c35 | 99 | buffer->ptr[OTA_SIZE_OFS ] = size_with_header & 0xFF; |
| MACRUM | 0:276e7a263c35 | 100 | buffer->ptr[OTA_SIZE_OFS + 1] = (size_with_header >> 8) & 0xFF; |
| MACRUM | 0:276e7a263c35 | 101 | buffer->ptr[OTA_SIZE_OFS + 2] = (size_with_header >> 16) & 0xFF; |
| MACRUM | 0:276e7a263c35 | 102 | buffer->ptr[OTA_SIZE_OFS + 3] = (size_with_header >> 24) & 0xFF; |
| MACRUM | 0:276e7a263c35 | 103 | |
| MACRUM | 0:276e7a263c35 | 104 | /* copy hash */ |
| MACRUM | 0:276e7a263c35 | 105 | for (size_t index = 0; index < ARM_UC_SHA256_SIZE; index++) |
| MACRUM | 0:276e7a263c35 | 106 | { |
| MACRUM | 0:276e7a263c35 | 107 | buffer->ptr[OTA_HASH_OFS + index] = details->hash[index]; |
| MACRUM | 0:276e7a263c35 | 108 | } |
| MACRUM | 0:276e7a263c35 | 109 | |
| MACRUM | 0:276e7a263c35 | 110 | /* copy campaign */ |
| MACRUM | 0:276e7a263c35 | 111 | for (size_t index = 0; index < ARM_UC_GUID_SIZE; index++) |
| MACRUM | 0:276e7a263c35 | 112 | { |
| MACRUM | 0:276e7a263c35 | 113 | buffer->ptr[OTA_CAMPAIGN_OFS + index] = details->campaign[index]; |
| MACRUM | 0:276e7a263c35 | 114 | } |
| MACRUM | 0:276e7a263c35 | 115 | |
| MACRUM | 0:276e7a263c35 | 116 | /* set buffer size minus CRC */ |
| MACRUM | 0:276e7a263c35 | 117 | buffer->size = HEADER_SIZE - 4; |
| MACRUM | 0:276e7a263c35 | 118 | |
| MACRUM | 0:276e7a263c35 | 119 | result.code = ERR_NONE; |
| MACRUM | 0:276e7a263c35 | 120 | } |
| MACRUM | 0:276e7a263c35 | 121 | |
| MACRUM | 0:276e7a263c35 | 122 | return result; |
| MACRUM | 0:276e7a263c35 | 123 | } |
| MACRUM | 0:276e7a263c35 | 124 | |
| MACRUM | 0:276e7a263c35 | 125 | /** |
| MACRUM | 0:276e7a263c35 | 126 | * @brief Read header for the image located at the base address. |
| MACRUM | 0:276e7a263c35 | 127 | * |
| MACRUM | 0:276e7a263c35 | 128 | * @param[in] base_address Start address for firmware slot. |
| MACRUM | 0:276e7a263c35 | 129 | * @param details Update client details struct. |
| MACRUM | 0:276e7a263c35 | 130 | * |
| MACRUM | 0:276e7a263c35 | 131 | * @return ERR_NONE on success, ERR_INVALID_PARAMETER on failure. |
| MACRUM | 0:276e7a263c35 | 132 | */ |
| MACRUM | 0:276e7a263c35 | 133 | static arm_uc_error_t arm_uc_pal_get_realtek_header(uint32_t base_address, |
| MACRUM | 0:276e7a263c35 | 134 | arm_uc_firmware_details_t* details) |
| MACRUM | 0:276e7a263c35 | 135 | { |
| MACRUM | 0:276e7a263c35 | 136 | arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER }; |
| MACRUM | 0:276e7a263c35 | 137 | |
| MACRUM | 0:276e7a263c35 | 138 | if (details) |
| MACRUM | 0:276e7a263c35 | 139 | { |
| MACRUM | 0:276e7a263c35 | 140 | uint8_t buffer[HEADER_SIZE] = { 0 }; |
| MACRUM | 0:276e7a263c35 | 141 | |
| MACRUM | 0:276e7a263c35 | 142 | int rc = arm_uc_flashiap_read(buffer, base_address, sizeof(buffer)); |
| MACRUM | 0:276e7a263c35 | 143 | |
| MACRUM | 0:276e7a263c35 | 144 | if (rc == 0) |
| MACRUM | 0:276e7a263c35 | 145 | { |
| MACRUM | 0:276e7a263c35 | 146 | #if 0 |
| MACRUM | 0:276e7a263c35 | 147 | printf("debug: \r\n"); |
| MACRUM | 0:276e7a263c35 | 148 | for (size_t index = 0; index < sizeof(buffer); index++) |
| MACRUM | 0:276e7a263c35 | 149 | { |
| MACRUM | 0:276e7a263c35 | 150 | printf("%02X", buffer[index]); |
| MACRUM | 0:276e7a263c35 | 151 | } |
| MACRUM | 0:276e7a263c35 | 152 | printf("\r\n"); |
| MACRUM | 0:276e7a263c35 | 153 | #endif |
| MACRUM | 0:276e7a263c35 | 154 | |
| MACRUM | 0:276e7a263c35 | 155 | /* parse tag */ |
| MACRUM | 0:276e7a263c35 | 156 | uint32_t tag = buffer[OTA_TAG_OFS + 3]; |
| MACRUM | 0:276e7a263c35 | 157 | tag = (tag << 8) | buffer[OTA_TAG_OFS + 2]; |
| MACRUM | 0:276e7a263c35 | 158 | tag = (tag << 8) | buffer[OTA_TAG_OFS + 1]; |
| MACRUM | 0:276e7a263c35 | 159 | tag = (tag << 8) | buffer[OTA_TAG_OFS + 0]; |
| MACRUM | 0:276e7a263c35 | 160 | |
| MACRUM | 0:276e7a263c35 | 161 | /* parse version tag */ |
| MACRUM | 0:276e7a263c35 | 162 | uint32_t version_tag = buffer[OTA_VER_OFS + 3]; |
| MACRUM | 0:276e7a263c35 | 163 | version_tag = (version_tag << 8) | buffer[OTA_VER_OFS + 2]; |
| MACRUM | 0:276e7a263c35 | 164 | version_tag = (version_tag << 8) | buffer[OTA_VER_OFS + 1]; |
| MACRUM | 0:276e7a263c35 | 165 | version_tag = (version_tag << 8) | buffer[OTA_VER_OFS + 0]; |
| MACRUM | 0:276e7a263c35 | 166 | |
| MACRUM | 0:276e7a263c35 | 167 | UC_PAAL_TRACE("tag: %" PRIX32, tag); |
| MACRUM | 0:276e7a263c35 | 168 | UC_PAAL_TRACE("version_tag: %" PRIX32, version_tag); |
| MACRUM | 0:276e7a263c35 | 169 | |
| MACRUM | 0:276e7a263c35 | 170 | /* check tags */ |
| MACRUM | 0:276e7a263c35 | 171 | if ((tag == OTA_TAG_ID) && (version_tag == OTA_VER_ID)) |
| MACRUM | 0:276e7a263c35 | 172 | { |
| MACRUM | 0:276e7a263c35 | 173 | /* parse CRC */ |
| MACRUM | 0:276e7a263c35 | 174 | uint32_t crc_header = buffer[OTA_CRC32_OFS + 3]; |
| MACRUM | 0:276e7a263c35 | 175 | crc_header = (crc_header << 8) | buffer[OTA_CRC32_OFS + 2]; |
| MACRUM | 0:276e7a263c35 | 176 | crc_header = (crc_header << 8) | buffer[OTA_CRC32_OFS + 1]; |
| MACRUM | 0:276e7a263c35 | 177 | crc_header = (crc_header << 8) | buffer[OTA_CRC32_OFS + 0]; |
| MACRUM | 0:276e7a263c35 | 178 | |
| MACRUM | 0:276e7a263c35 | 179 | /* calculate crc */ |
| MACRUM | 0:276e7a263c35 | 180 | uint32_t crc_calculated = arm_uc_crc32(buffer, OTA_CRC32_OFS); |
| MACRUM | 0:276e7a263c35 | 181 | |
| MACRUM | 0:276e7a263c35 | 182 | UC_PAAL_TRACE("CRC header: %" PRIX32, crc_header); |
| MACRUM | 0:276e7a263c35 | 183 | UC_PAAL_TRACE("CRC calculated: %" PRIX32, crc_calculated); |
| MACRUM | 0:276e7a263c35 | 184 | |
| MACRUM | 0:276e7a263c35 | 185 | /* check crc before proceeding */ |
| MACRUM | 0:276e7a263c35 | 186 | if (crc_header == crc_calculated) |
| MACRUM | 0:276e7a263c35 | 187 | { |
| MACRUM | 0:276e7a263c35 | 188 | /* parse size */ |
| MACRUM | 0:276e7a263c35 | 189 | uint32_t size = buffer[OTA_SIZE_OFS + 3]; |
| MACRUM | 0:276e7a263c35 | 190 | size = (size << 8) | buffer[OTA_SIZE_OFS + 2]; |
| MACRUM | 0:276e7a263c35 | 191 | size = (size << 8) | buffer[OTA_SIZE_OFS + 1]; |
| MACRUM | 0:276e7a263c35 | 192 | size = (size << 8) | buffer[OTA_SIZE_OFS + 0]; |
| MACRUM | 0:276e7a263c35 | 193 | |
| MACRUM | 0:276e7a263c35 | 194 | /* parse version */ |
| MACRUM | 0:276e7a263c35 | 195 | uint64_t version = buffer[OTA_EPOCH_OFS + 7]; |
| MACRUM | 0:276e7a263c35 | 196 | version = (version << 8) | buffer[OTA_EPOCH_OFS + 6]; |
| MACRUM | 0:276e7a263c35 | 197 | version = (version << 8) | buffer[OTA_EPOCH_OFS + 5]; |
| MACRUM | 0:276e7a263c35 | 198 | version = (version << 8) | buffer[OTA_EPOCH_OFS + 4]; |
| MACRUM | 0:276e7a263c35 | 199 | version = (version << 8) | buffer[OTA_EPOCH_OFS + 3]; |
| MACRUM | 0:276e7a263c35 | 200 | version = (version << 8) | buffer[OTA_EPOCH_OFS + 2]; |
| MACRUM | 0:276e7a263c35 | 201 | version = (version << 8) | buffer[OTA_EPOCH_OFS + 1]; |
| MACRUM | 0:276e7a263c35 | 202 | version = (version << 8) | buffer[OTA_EPOCH_OFS + 0]; |
| MACRUM | 0:276e7a263c35 | 203 | |
| MACRUM | 0:276e7a263c35 | 204 | /* copy hash */ |
| MACRUM | 0:276e7a263c35 | 205 | for (size_t index = 0; index < ARM_UC_SHA256_SIZE; index++) |
| MACRUM | 0:276e7a263c35 | 206 | { |
| MACRUM | 0:276e7a263c35 | 207 | details->hash[index] = buffer[OTA_HASH_OFS + index]; |
| MACRUM | 0:276e7a263c35 | 208 | } |
| MACRUM | 0:276e7a263c35 | 209 | |
| MACRUM | 0:276e7a263c35 | 210 | details->size = size - HEADER_SIZE; |
| MACRUM | 0:276e7a263c35 | 211 | details->version = version; |
| MACRUM | 0:276e7a263c35 | 212 | |
| MACRUM | 0:276e7a263c35 | 213 | UC_PAAL_TRACE("size: %" PRIu64, details->size); |
| MACRUM | 0:276e7a263c35 | 214 | UC_PAAL_TRACE("version: %" PRIu64, details->version); |
| MACRUM | 0:276e7a263c35 | 215 | |
| MACRUM | 0:276e7a263c35 | 216 | #if 0 |
| MACRUM | 0:276e7a263c35 | 217 | printf("hash: "); |
| MACRUM | 0:276e7a263c35 | 218 | for (size_t index = 0; index < ARM_UC_SHA256_SIZE; index++) |
| MACRUM | 0:276e7a263c35 | 219 | { |
| MACRUM | 0:276e7a263c35 | 220 | printf("%02X", details->hash[index]); |
| MACRUM | 0:276e7a263c35 | 221 | } |
| MACRUM | 0:276e7a263c35 | 222 | printf("\r\n"); |
| MACRUM | 0:276e7a263c35 | 223 | #endif |
| MACRUM | 0:276e7a263c35 | 224 | |
| MACRUM | 0:276e7a263c35 | 225 | result.code = ERR_NONE; |
| MACRUM | 0:276e7a263c35 | 226 | } |
| MACRUM | 0:276e7a263c35 | 227 | else |
| MACRUM | 0:276e7a263c35 | 228 | { |
| MACRUM | 0:276e7a263c35 | 229 | UC_PAAL_ERR_MSG("header crc check failed"); |
| MACRUM | 0:276e7a263c35 | 230 | } |
| MACRUM | 0:276e7a263c35 | 231 | } |
| MACRUM | 0:276e7a263c35 | 232 | else |
| MACRUM | 0:276e7a263c35 | 233 | { |
| MACRUM | 0:276e7a263c35 | 234 | UC_PAAL_ERR_MSG("invalid header"); |
| MACRUM | 0:276e7a263c35 | 235 | } |
| MACRUM | 0:276e7a263c35 | 236 | } |
| MACRUM | 0:276e7a263c35 | 237 | else |
| MACRUM | 0:276e7a263c35 | 238 | { |
| MACRUM | 0:276e7a263c35 | 239 | UC_PAAL_ERR_MSG("error reading from flash"); |
| MACRUM | 0:276e7a263c35 | 240 | } |
| MACRUM | 0:276e7a263c35 | 241 | } |
| MACRUM | 0:276e7a263c35 | 242 | |
| MACRUM | 0:276e7a263c35 | 243 | return result; |
| MACRUM | 0:276e7a263c35 | 244 | } |
| MACRUM | 0:276e7a263c35 | 245 | |
| MACRUM | 0:276e7a263c35 | 246 | /** |
| MACRUM | 0:276e7a263c35 | 247 | * @brief Find base address of either running or spare firmare slot. |
| MACRUM | 0:276e7a263c35 | 248 | * |
| MACRUM | 0:276e7a263c35 | 249 | * @param[in] find Enum specifying what to find (running or spare slot). |
| MACRUM | 0:276e7a263c35 | 250 | * |
| MACRUM | 0:276e7a263c35 | 251 | * @return Base address. |
| MACRUM | 0:276e7a263c35 | 252 | */ |
| MACRUM | 0:276e7a263c35 | 253 | static uint32_t arm_uc_pal_find_base_address(base_address_t find) |
| MACRUM | 0:276e7a263c35 | 254 | { |
| MACRUM | 0:276e7a263c35 | 255 | uint32_t base_address = 0; |
| MACRUM | 0:276e7a263c35 | 256 | |
| MACRUM | 0:276e7a263c35 | 257 | arm_uc_firmware_details_t slot_0 = { 0 }; |
| MACRUM | 0:276e7a263c35 | 258 | arm_uc_firmware_details_t slot_1 = { 0 }; |
| MACRUM | 0:276e7a263c35 | 259 | |
| MACRUM | 0:276e7a263c35 | 260 | /* read header from both slots */ |
| MACRUM | 0:276e7a263c35 | 261 | arm_uc_error_t result_0 = arm_uc_pal_get_realtek_header(OTA_REGION1_BASE, &slot_0); |
| MACRUM | 0:276e7a263c35 | 262 | arm_uc_error_t result_1 = arm_uc_pal_get_realtek_header(OTA_REGION2_BASE, &slot_1); |
| MACRUM | 0:276e7a263c35 | 263 | |
| MACRUM | 0:276e7a263c35 | 264 | /* both headers are valid */ |
| MACRUM | 0:276e7a263c35 | 265 | if ((result_0.error == ERR_NONE) && (result_1.error == ERR_NONE)) |
| MACRUM | 0:276e7a263c35 | 266 | { |
| MACRUM | 0:276e7a263c35 | 267 | /* running firmware has the highest version number */ |
| MACRUM | 0:276e7a263c35 | 268 | if (find == BASE_ADDRESS_RUNNING) |
| MACRUM | 0:276e7a263c35 | 269 | { |
| MACRUM | 0:276e7a263c35 | 270 | base_address = (slot_0.version >= slot_1.version) ? OTA_REGION1_BASE : OTA_REGION2_BASE; |
| MACRUM | 0:276e7a263c35 | 271 | } |
| MACRUM | 0:276e7a263c35 | 272 | /* spare firmware has the lowest version number */ |
| MACRUM | 0:276e7a263c35 | 273 | else |
| MACRUM | 0:276e7a263c35 | 274 | { |
| MACRUM | 0:276e7a263c35 | 275 | /* same test, swap result */ |
| MACRUM | 0:276e7a263c35 | 276 | base_address = (slot_0.version >= slot_1.version) ? OTA_REGION2_BASE : OTA_REGION1_BASE; |
| MACRUM | 0:276e7a263c35 | 277 | } |
| MACRUM | 0:276e7a263c35 | 278 | } |
| MACRUM | 0:276e7a263c35 | 279 | /* only slot0 has a valid header */ |
| MACRUM | 0:276e7a263c35 | 280 | else if (result_0.error == ERR_NONE) |
| MACRUM | 0:276e7a263c35 | 281 | { |
| MACRUM | 0:276e7a263c35 | 282 | if (find == BASE_ADDRESS_RUNNING) |
| MACRUM | 0:276e7a263c35 | 283 | { |
| MACRUM | 0:276e7a263c35 | 284 | /* only valid header must be the running one */ |
| MACRUM | 0:276e7a263c35 | 285 | base_address = OTA_REGION1_BASE; |
| MACRUM | 0:276e7a263c35 | 286 | } |
| MACRUM | 0:276e7a263c35 | 287 | else |
| MACRUM | 0:276e7a263c35 | 288 | { |
| MACRUM | 0:276e7a263c35 | 289 | /* slot with invalid header can be used as spare */ |
| MACRUM | 0:276e7a263c35 | 290 | base_address = OTA_REGION2_BASE; |
| MACRUM | 0:276e7a263c35 | 291 | } |
| MACRUM | 0:276e7a263c35 | 292 | } |
| MACRUM | 0:276e7a263c35 | 293 | /* only slot1 has a valid header */ |
| MACRUM | 0:276e7a263c35 | 294 | else if (result_1.error == ERR_NONE) |
| MACRUM | 0:276e7a263c35 | 295 | { |
| MACRUM | 0:276e7a263c35 | 296 | if (find == BASE_ADDRESS_RUNNING) |
| MACRUM | 0:276e7a263c35 | 297 | { |
| MACRUM | 0:276e7a263c35 | 298 | /* only valid header must be the running one */ |
| MACRUM | 0:276e7a263c35 | 299 | base_address = OTA_REGION2_BASE; |
| MACRUM | 0:276e7a263c35 | 300 | } |
| MACRUM | 0:276e7a263c35 | 301 | else |
| MACRUM | 0:276e7a263c35 | 302 | { |
| MACRUM | 0:276e7a263c35 | 303 | /* slot with invalid header can be used as spare */ |
| MACRUM | 0:276e7a263c35 | 304 | base_address = OTA_REGION1_BASE; |
| MACRUM | 0:276e7a263c35 | 305 | } |
| MACRUM | 0:276e7a263c35 | 306 | } |
| MACRUM | 0:276e7a263c35 | 307 | |
| MACRUM | 0:276e7a263c35 | 308 | /* if both headers are invalid return 0 */ |
| MACRUM | 0:276e7a263c35 | 309 | |
| MACRUM | 0:276e7a263c35 | 310 | return base_address; |
| MACRUM | 0:276e7a263c35 | 311 | } |
| MACRUM | 0:276e7a263c35 | 312 | |
| MACRUM | 0:276e7a263c35 | 313 | /*****************************************************************************/ |
| MACRUM | 0:276e7a263c35 | 314 | |
| MACRUM | 0:276e7a263c35 | 315 | arm_uc_error_t ARM_UC_PAL_RTL8195AM_Initialize(void (*callback)(uint32_t)) |
| MACRUM | 0:276e7a263c35 | 316 | { |
| MACRUM | 0:276e7a263c35 | 317 | arm_uc_error_t result = { .code = ERR_NONE }; |
| MACRUM | 0:276e7a263c35 | 318 | |
| MACRUM | 0:276e7a263c35 | 319 | arm_uc_pal_rtl8195am_callback = callback; |
| MACRUM | 0:276e7a263c35 | 320 | |
| MACRUM | 0:276e7a263c35 | 321 | return result; |
| MACRUM | 0:276e7a263c35 | 322 | } |
| MACRUM | 0:276e7a263c35 | 323 | |
| MACRUM | 0:276e7a263c35 | 324 | /** |
| MACRUM | 0:276e7a263c35 | 325 | * @brief Get maximum number of supported storage locations. |
| MACRUM | 0:276e7a263c35 | 326 | * |
| MACRUM | 0:276e7a263c35 | 327 | * @return Number of storage locations. |
| MACRUM | 0:276e7a263c35 | 328 | */ |
| MACRUM | 0:276e7a263c35 | 329 | uint32_t ARM_UC_PAL_RTL8195AM_GetMaxID(void) |
| MACRUM | 0:276e7a263c35 | 330 | { |
| MACRUM | 0:276e7a263c35 | 331 | return 2; |
| MACRUM | 0:276e7a263c35 | 332 | } |
| MACRUM | 0:276e7a263c35 | 333 | |
| MACRUM | 0:276e7a263c35 | 334 | /** |
| MACRUM | 0:276e7a263c35 | 335 | * @brief Prepare the storage layer for a new firmware image. |
| MACRUM | 0:276e7a263c35 | 336 | * @details The storage location is set up to receive an image with |
| MACRUM | 0:276e7a263c35 | 337 | * the details passed in the details struct. |
| MACRUM | 0:276e7a263c35 | 338 | * |
| MACRUM | 0:276e7a263c35 | 339 | * @param location Storage location ID. |
| MACRUM | 0:276e7a263c35 | 340 | * @param details Pointer to a struct with firmware details. |
| MACRUM | 0:276e7a263c35 | 341 | * @param buffer Temporary buffer for formatting and storing metadata. |
| MACRUM | 0:276e7a263c35 | 342 | * @return Returns ERR_NONE on accept, and signals the event handler with |
| MACRUM | 0:276e7a263c35 | 343 | * either DONE or ERROR when complete. |
| MACRUM | 0:276e7a263c35 | 344 | * Returns ERR_INVALID_PARAMETER on reject, and no signal is sent. |
| MACRUM | 0:276e7a263c35 | 345 | */ |
| MACRUM | 0:276e7a263c35 | 346 | arm_uc_error_t ARM_UC_PAL_RTL8195AM_Prepare(uint32_t location, |
| MACRUM | 0:276e7a263c35 | 347 | const arm_uc_firmware_details_t* details, |
| MACRUM | 0:276e7a263c35 | 348 | arm_uc_buffer_t* buffer) |
| MACRUM | 0:276e7a263c35 | 349 | { |
| MACRUM | 0:276e7a263c35 | 350 | arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER }; |
| MACRUM | 0:276e7a263c35 | 351 | |
| MACRUM | 0:276e7a263c35 | 352 | if (details && buffer && buffer->ptr) |
| MACRUM | 0:276e7a263c35 | 353 | { |
| MACRUM | 0:276e7a263c35 | 354 | UC_PAAL_TRACE("Prepare: %" PRIX32 " %" PRIX64 " %" PRIu64, |
| MACRUM | 0:276e7a263c35 | 355 | location, |
| MACRUM | 0:276e7a263c35 | 356 | details->size, |
| MACRUM | 0:276e7a263c35 | 357 | details->version); |
| MACRUM | 0:276e7a263c35 | 358 | |
| MACRUM | 0:276e7a263c35 | 359 | /* find location for the spare slot */ |
| MACRUM | 0:276e7a263c35 | 360 | arm_uc_base_address = arm_uc_pal_find_base_address(BASE_ADDRESS_SPARE); |
| MACRUM | 0:276e7a263c35 | 361 | |
| MACRUM | 0:276e7a263c35 | 362 | UC_PAAL_TRACE("spare base: %" PRIX32, arm_uc_base_address); |
| MACRUM | 0:276e7a263c35 | 363 | |
| MACRUM | 0:276e7a263c35 | 364 | /* check that the firmware can fit the spare slot */ |
| MACRUM | 0:276e7a263c35 | 365 | if (((arm_uc_base_address == OTA_REGION1_BASE) && (details->size < OTA_REGION1_SIZE)) || |
| MACRUM | 0:276e7a263c35 | 366 | ((arm_uc_base_address == OTA_REGION2_BASE) && (details->size < OTA_REGION2_SIZE))) |
| MACRUM | 0:276e7a263c35 | 367 | { |
| MACRUM | 0:276e7a263c35 | 368 | /* encode firmware details in buffer */ |
| MACRUM | 0:276e7a263c35 | 369 | result = arm_uc_pal_create_realtek_header(details, buffer); |
| MACRUM | 0:276e7a263c35 | 370 | |
| MACRUM | 0:276e7a263c35 | 371 | /* make space for new firmware */ |
| MACRUM | 0:276e7a263c35 | 372 | if (result.error == ERR_NONE) |
| MACRUM | 0:276e7a263c35 | 373 | { |
| MACRUM | 0:276e7a263c35 | 374 | /* find end address */ |
| MACRUM | 0:276e7a263c35 | 375 | uint32_t end_address = arm_uc_base_address + HEADER_SIZE + details->size; |
| MACRUM | 0:276e7a263c35 | 376 | |
| MACRUM | 0:276e7a263c35 | 377 | /* erase */ |
| MACRUM | 0:276e7a263c35 | 378 | uint32_t erase_address = arm_uc_base_address; |
| MACRUM | 0:276e7a263c35 | 379 | |
| MACRUM | 0:276e7a263c35 | 380 | while (erase_address < end_address) |
| MACRUM | 0:276e7a263c35 | 381 | { |
| MACRUM | 0:276e7a263c35 | 382 | uint32_t sector_size = arm_uc_flashiap_get_sector_size(erase_address); |
| MACRUM | 0:276e7a263c35 | 383 | |
| MACRUM | 0:276e7a263c35 | 384 | int status = arm_uc_flashiap_erase(erase_address, sector_size); |
| MACRUM | 0:276e7a263c35 | 385 | |
| MACRUM | 0:276e7a263c35 | 386 | UC_PAAL_TRACE("erase: %" PRIX32 " %" PRIX32 " %d", |
| MACRUM | 0:276e7a263c35 | 387 | erase_address, |
| MACRUM | 0:276e7a263c35 | 388 | sector_size, |
| MACRUM | 0:276e7a263c35 | 389 | status); |
| MACRUM | 0:276e7a263c35 | 390 | |
| MACRUM | 0:276e7a263c35 | 391 | if (status == 0) |
| MACRUM | 0:276e7a263c35 | 392 | { |
| MACRUM | 0:276e7a263c35 | 393 | erase_address += sector_size; |
| MACRUM | 0:276e7a263c35 | 394 | } |
| MACRUM | 0:276e7a263c35 | 395 | else |
| MACRUM | 0:276e7a263c35 | 396 | { |
| MACRUM | 0:276e7a263c35 | 397 | result.code = ERR_INVALID_PARAMETER; |
| MACRUM | 0:276e7a263c35 | 398 | break; |
| MACRUM | 0:276e7a263c35 | 399 | } |
| MACRUM | 0:276e7a263c35 | 400 | } |
| MACRUM | 0:276e7a263c35 | 401 | |
| MACRUM | 0:276e7a263c35 | 402 | /* write header */ |
| MACRUM | 0:276e7a263c35 | 403 | if (result.error == ERR_NONE) |
| MACRUM | 0:276e7a263c35 | 404 | { |
| MACRUM | 0:276e7a263c35 | 405 | UC_PAAL_TRACE("program: %u %" PRIu32, |
| MACRUM | 0:276e7a263c35 | 406 | arm_uc_base_address, |
| MACRUM | 0:276e7a263c35 | 407 | buffer->size); |
| MACRUM | 0:276e7a263c35 | 408 | |
| MACRUM | 0:276e7a263c35 | 409 | /* set default return code */ |
| MACRUM | 0:276e7a263c35 | 410 | result.code = ERR_NONE; |
| MACRUM | 0:276e7a263c35 | 411 | |
| MACRUM | 0:276e7a263c35 | 412 | /* write header without CRC */ |
| MACRUM | 0:276e7a263c35 | 413 | int status = arm_uc_flashiap_program(buffer->ptr, |
| MACRUM | 0:276e7a263c35 | 414 | arm_uc_base_address, |
| MACRUM | 0:276e7a263c35 | 415 | buffer->size); |
| MACRUM | 0:276e7a263c35 | 416 | |
| MACRUM | 0:276e7a263c35 | 417 | if (status != 0) |
| MACRUM | 0:276e7a263c35 | 418 | { |
| MACRUM | 0:276e7a263c35 | 419 | /* set return code */ |
| MACRUM | 0:276e7a263c35 | 420 | result.code = ERR_INVALID_PARAMETER; |
| MACRUM | 0:276e7a263c35 | 421 | } |
| MACRUM | 0:276e7a263c35 | 422 | |
| MACRUM | 0:276e7a263c35 | 423 | if (result.error == ERR_NONE) |
| MACRUM | 0:276e7a263c35 | 424 | { |
| MACRUM | 0:276e7a263c35 | 425 | /* signal done */ |
| MACRUM | 0:276e7a263c35 | 426 | arm_uc_pal_rtl8195am_signal_internal(ARM_UC_PAAL_EVENT_PREPARE_DONE); |
| MACRUM | 0:276e7a263c35 | 427 | } |
| MACRUM | 0:276e7a263c35 | 428 | else |
| MACRUM | 0:276e7a263c35 | 429 | { |
| MACRUM | 0:276e7a263c35 | 430 | UC_PAAL_ERR_MSG("flash program failed"); |
| MACRUM | 0:276e7a263c35 | 431 | } |
| MACRUM | 0:276e7a263c35 | 432 | } |
| MACRUM | 0:276e7a263c35 | 433 | else |
| MACRUM | 0:276e7a263c35 | 434 | { |
| MACRUM | 0:276e7a263c35 | 435 | UC_PAAL_ERR_MSG("flash erase failed"); |
| MACRUM | 0:276e7a263c35 | 436 | } |
| MACRUM | 0:276e7a263c35 | 437 | } |
| MACRUM | 0:276e7a263c35 | 438 | else |
| MACRUM | 0:276e7a263c35 | 439 | { |
| MACRUM | 0:276e7a263c35 | 440 | UC_PAAL_ERR_MSG("create header failed"); |
| MACRUM | 0:276e7a263c35 | 441 | } |
| MACRUM | 0:276e7a263c35 | 442 | } |
| MACRUM | 0:276e7a263c35 | 443 | else |
| MACRUM | 0:276e7a263c35 | 444 | { |
| MACRUM | 0:276e7a263c35 | 445 | UC_PAAL_ERR_MSG("firmware larger than slot"); |
| MACRUM | 0:276e7a263c35 | 446 | } |
| MACRUM | 0:276e7a263c35 | 447 | } |
| MACRUM | 0:276e7a263c35 | 448 | |
| MACRUM | 0:276e7a263c35 | 449 | return result; |
| MACRUM | 0:276e7a263c35 | 450 | } |
| MACRUM | 0:276e7a263c35 | 451 | |
| MACRUM | 0:276e7a263c35 | 452 | /** |
| MACRUM | 0:276e7a263c35 | 453 | * @brief Write a fragment to the indicated storage location. |
| MACRUM | 0:276e7a263c35 | 454 | * @details The storage location must have been allocated using the Prepare |
| MACRUM | 0:276e7a263c35 | 455 | * call. The call is expected to write the entire fragment before |
| MACRUM | 0:276e7a263c35 | 456 | * signaling completion. |
| MACRUM | 0:276e7a263c35 | 457 | * |
| MACRUM | 0:276e7a263c35 | 458 | * @param location Storage location ID. |
| MACRUM | 0:276e7a263c35 | 459 | * @param offset Offset in bytes to where the fragment should be written. |
| MACRUM | 0:276e7a263c35 | 460 | * @param buffer Pointer to buffer struct with fragment. |
| MACRUM | 0:276e7a263c35 | 461 | * @return Returns ERR_NONE on accept, and signals the event handler with |
| MACRUM | 0:276e7a263c35 | 462 | * either DONE or ERROR when complete. |
| MACRUM | 0:276e7a263c35 | 463 | * Returns ERR_INVALID_PARAMETER on reject, and no signal is sent. |
| MACRUM | 0:276e7a263c35 | 464 | */ |
| MACRUM | 0:276e7a263c35 | 465 | arm_uc_error_t ARM_UC_PAL_RTL8195AM_Write(uint32_t location, |
| MACRUM | 0:276e7a263c35 | 466 | uint32_t offset, |
| MACRUM | 0:276e7a263c35 | 467 | const arm_uc_buffer_t* buffer) |
| MACRUM | 0:276e7a263c35 | 468 | { |
| MACRUM | 0:276e7a263c35 | 469 | arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER }; |
| MACRUM | 0:276e7a263c35 | 470 | |
| MACRUM | 0:276e7a263c35 | 471 | if (buffer && buffer->ptr) |
| MACRUM | 0:276e7a263c35 | 472 | { |
| MACRUM | 0:276e7a263c35 | 473 | /* find location address */ |
| MACRUM | 0:276e7a263c35 | 474 | uint32_t physical_address = arm_uc_base_address + HEADER_SIZE + offset; |
| MACRUM | 0:276e7a263c35 | 475 | |
| MACRUM | 0:276e7a263c35 | 476 | UC_PAAL_TRACE("Write: %p %" PRIX32 " %" PRIX32 " %" PRIX32, |
| MACRUM | 0:276e7a263c35 | 477 | buffer->ptr, |
| MACRUM | 0:276e7a263c35 | 478 | buffer->size, |
| MACRUM | 0:276e7a263c35 | 479 | offset, |
| MACRUM | 0:276e7a263c35 | 480 | physical_address); |
| MACRUM | 0:276e7a263c35 | 481 | |
| MACRUM | 0:276e7a263c35 | 482 | /* set default return code */ |
| MACRUM | 0:276e7a263c35 | 483 | result.code = ERR_NONE; |
| MACRUM | 0:276e7a263c35 | 484 | |
| MACRUM | 0:276e7a263c35 | 485 | for (size_t index = 0; index < buffer->size; ) |
| MACRUM | 0:276e7a263c35 | 486 | { |
| MACRUM | 0:276e7a263c35 | 487 | /* write aligned */ |
| MACRUM | 0:276e7a263c35 | 488 | size_t modulo = (physical_address + index) % FLASH_PAGE_SIZE; |
| MACRUM | 0:276e7a263c35 | 489 | size_t remaining = buffer->size - index; |
| MACRUM | 0:276e7a263c35 | 490 | size_t write_size = 0; |
| MACRUM | 0:276e7a263c35 | 491 | |
| MACRUM | 0:276e7a263c35 | 492 | /* fill remaining flash page */ |
| MACRUM | 0:276e7a263c35 | 493 | if (modulo > 0) |
| MACRUM | 0:276e7a263c35 | 494 | { |
| MACRUM | 0:276e7a263c35 | 495 | write_size = modulo; |
| MACRUM | 0:276e7a263c35 | 496 | } |
| MACRUM | 0:276e7a263c35 | 497 | /* write last page */ |
| MACRUM | 0:276e7a263c35 | 498 | else if (remaining < FLASH_PAGE_SIZE) |
| MACRUM | 0:276e7a263c35 | 499 | { |
| MACRUM | 0:276e7a263c35 | 500 | write_size = remaining; |
| MACRUM | 0:276e7a263c35 | 501 | } |
| MACRUM | 0:276e7a263c35 | 502 | /* write full page */ |
| MACRUM | 0:276e7a263c35 | 503 | else |
| MACRUM | 0:276e7a263c35 | 504 | { |
| MACRUM | 0:276e7a263c35 | 505 | write_size = FLASH_PAGE_SIZE; |
| MACRUM | 0:276e7a263c35 | 506 | } |
| MACRUM | 0:276e7a263c35 | 507 | |
| MACRUM | 0:276e7a263c35 | 508 | int status = arm_uc_flashiap_program(&buffer->ptr[index], |
| MACRUM | 0:276e7a263c35 | 509 | physical_address + index, |
| MACRUM | 0:276e7a263c35 | 510 | write_size); |
| MACRUM | 0:276e7a263c35 | 511 | |
| MACRUM | 0:276e7a263c35 | 512 | if (status != 0) |
| MACRUM | 0:276e7a263c35 | 513 | { |
| MACRUM | 0:276e7a263c35 | 514 | /* set return code */ |
| MACRUM | 0:276e7a263c35 | 515 | result.code = ERR_INVALID_PARAMETER; |
| MACRUM | 0:276e7a263c35 | 516 | break; |
| MACRUM | 0:276e7a263c35 | 517 | } |
| MACRUM | 0:276e7a263c35 | 518 | |
| MACRUM | 0:276e7a263c35 | 519 | index += write_size; |
| MACRUM | 0:276e7a263c35 | 520 | } |
| MACRUM | 0:276e7a263c35 | 521 | |
| MACRUM | 0:276e7a263c35 | 522 | if (result.error == ERR_NONE) |
| MACRUM | 0:276e7a263c35 | 523 | { |
| MACRUM | 0:276e7a263c35 | 524 | /* signal done */ |
| MACRUM | 0:276e7a263c35 | 525 | arm_uc_pal_rtl8195am_signal_internal(ARM_UC_PAAL_EVENT_WRITE_DONE); |
| MACRUM | 0:276e7a263c35 | 526 | } |
| MACRUM | 0:276e7a263c35 | 527 | else |
| MACRUM | 0:276e7a263c35 | 528 | { |
| MACRUM | 0:276e7a263c35 | 529 | UC_PAAL_ERR_MSG("flash program failed"); |
| MACRUM | 0:276e7a263c35 | 530 | } |
| MACRUM | 0:276e7a263c35 | 531 | } |
| MACRUM | 0:276e7a263c35 | 532 | |
| MACRUM | 0:276e7a263c35 | 533 | return result; |
| MACRUM | 0:276e7a263c35 | 534 | } |
| MACRUM | 0:276e7a263c35 | 535 | |
| MACRUM | 0:276e7a263c35 | 536 | /** |
| MACRUM | 0:276e7a263c35 | 537 | * @brief Close storage location for writing and flush pending data. |
| MACRUM | 0:276e7a263c35 | 538 | * |
| MACRUM | 0:276e7a263c35 | 539 | * @param location Storage location ID. |
| MACRUM | 0:276e7a263c35 | 540 | * @return Returns ERR_NONE on accept, and signals the event handler with |
| MACRUM | 0:276e7a263c35 | 541 | * either DONE or ERROR when complete. |
| MACRUM | 0:276e7a263c35 | 542 | * Returns ERR_INVALID_PARAMETER on reject, and no signal is sent. |
| MACRUM | 0:276e7a263c35 | 543 | */ |
| MACRUM | 0:276e7a263c35 | 544 | arm_uc_error_t ARM_UC_PAL_RTL8195AM_Finalize(uint32_t location) |
| MACRUM | 0:276e7a263c35 | 545 | { |
| MACRUM | 0:276e7a263c35 | 546 | arm_uc_error_t result = { .code = ERR_NONE }; |
| MACRUM | 0:276e7a263c35 | 547 | |
| MACRUM | 0:276e7a263c35 | 548 | UC_PAAL_TRACE("Finalize"); |
| MACRUM | 0:276e7a263c35 | 549 | |
| MACRUM | 0:276e7a263c35 | 550 | arm_uc_pal_rtl8195am_signal_internal(ARM_UC_PAAL_EVENT_FINALIZE_DONE); |
| MACRUM | 0:276e7a263c35 | 551 | |
| MACRUM | 0:276e7a263c35 | 552 | return result; |
| MACRUM | 0:276e7a263c35 | 553 | } |
| MACRUM | 0:276e7a263c35 | 554 | |
| MACRUM | 0:276e7a263c35 | 555 | /** |
| MACRUM | 0:276e7a263c35 | 556 | * @brief Read a fragment from the indicated storage location. |
| MACRUM | 0:276e7a263c35 | 557 | * @details The function will read until the buffer is full or the end of |
| MACRUM | 0:276e7a263c35 | 558 | * the storage location has been reached. The actual amount of |
| MACRUM | 0:276e7a263c35 | 559 | * bytes read is set in the buffer struct. |
| MACRUM | 0:276e7a263c35 | 560 | * |
| MACRUM | 0:276e7a263c35 | 561 | * @param location Storage location ID. |
| MACRUM | 0:276e7a263c35 | 562 | * @param offset Offset in bytes to read from. |
| MACRUM | 0:276e7a263c35 | 563 | * @param buffer Pointer to buffer struct to store fragment. buffer->size |
| MACRUM | 0:276e7a263c35 | 564 | * contains the intended read size. |
| MACRUM | 0:276e7a263c35 | 565 | * @return Returns ERR_NONE on accept, and signals the event handler with |
| MACRUM | 0:276e7a263c35 | 566 | * either DONE or ERROR when complete. |
| MACRUM | 0:276e7a263c35 | 567 | * Returns ERR_INVALID_PARAMETER on reject, and no signal is sent. |
| MACRUM | 0:276e7a263c35 | 568 | * buffer->size contains actual bytes read on return. |
| MACRUM | 0:276e7a263c35 | 569 | */ |
| MACRUM | 0:276e7a263c35 | 570 | arm_uc_error_t ARM_UC_PAL_RTL8195AM_Read(uint32_t location, |
| MACRUM | 0:276e7a263c35 | 571 | uint32_t offset, |
| MACRUM | 0:276e7a263c35 | 572 | arm_uc_buffer_t* buffer) |
| MACRUM | 0:276e7a263c35 | 573 | { |
| MACRUM | 0:276e7a263c35 | 574 | arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER }; |
| MACRUM | 0:276e7a263c35 | 575 | |
| MACRUM | 0:276e7a263c35 | 576 | if (buffer && buffer->ptr) |
| MACRUM | 0:276e7a263c35 | 577 | { |
| MACRUM | 0:276e7a263c35 | 578 | /* find the base address for the spare slot if not already set */ |
| MACRUM | 0:276e7a263c35 | 579 | if (arm_uc_base_address == 0) |
| MACRUM | 0:276e7a263c35 | 580 | { |
| MACRUM | 0:276e7a263c35 | 581 | arm_uc_base_address = arm_uc_pal_find_base_address(BASE_ADDRESS_SPARE); |
| MACRUM | 0:276e7a263c35 | 582 | } |
| MACRUM | 0:276e7a263c35 | 583 | |
| MACRUM | 0:276e7a263c35 | 584 | /* calculate actual physical address */ |
| MACRUM | 0:276e7a263c35 | 585 | uint32_t physical_address = arm_uc_base_address + HEADER_SIZE + offset; |
| MACRUM | 0:276e7a263c35 | 586 | |
| MACRUM | 0:276e7a263c35 | 587 | UC_PAAL_TRACE("Read: %" PRIX32 " %" PRIX32 " %" PRIX32, |
| MACRUM | 0:276e7a263c35 | 588 | physical_address, |
| MACRUM | 0:276e7a263c35 | 589 | offset, |
| MACRUM | 0:276e7a263c35 | 590 | buffer->size); |
| MACRUM | 0:276e7a263c35 | 591 | |
| MACRUM | 0:276e7a263c35 | 592 | uint32_t read_size = buffer->size; |
| MACRUM | 0:276e7a263c35 | 593 | |
| MACRUM | 0:276e7a263c35 | 594 | int status = arm_uc_flashiap_read(buffer->ptr, physical_address, read_size); |
| MACRUM | 0:276e7a263c35 | 595 | |
| MACRUM | 0:276e7a263c35 | 596 | if (status == 0) |
| MACRUM | 0:276e7a263c35 | 597 | { |
| MACRUM | 0:276e7a263c35 | 598 | /* set buffer size */ |
| MACRUM | 0:276e7a263c35 | 599 | buffer->size = read_size; |
| MACRUM | 0:276e7a263c35 | 600 | |
| MACRUM | 0:276e7a263c35 | 601 | /* set return code */ |
| MACRUM | 0:276e7a263c35 | 602 | result.code = ERR_NONE; |
| MACRUM | 0:276e7a263c35 | 603 | |
| MACRUM | 0:276e7a263c35 | 604 | /* signal done */ |
| MACRUM | 0:276e7a263c35 | 605 | arm_uc_pal_rtl8195am_signal_internal(ARM_UC_PAAL_EVENT_READ_DONE); |
| MACRUM | 0:276e7a263c35 | 606 | } |
| MACRUM | 0:276e7a263c35 | 607 | else |
| MACRUM | 0:276e7a263c35 | 608 | { |
| MACRUM | 0:276e7a263c35 | 609 | UC_PAAL_ERR_MSG("flash read failed"); |
| MACRUM | 0:276e7a263c35 | 610 | } |
| MACRUM | 0:276e7a263c35 | 611 | } |
| MACRUM | 0:276e7a263c35 | 612 | |
| MACRUM | 0:276e7a263c35 | 613 | return result; |
| MACRUM | 0:276e7a263c35 | 614 | } |
| MACRUM | 0:276e7a263c35 | 615 | |
| MACRUM | 0:276e7a263c35 | 616 | /** |
| MACRUM | 0:276e7a263c35 | 617 | * @brief Set the firmware image in the slot to be the new active image. |
| MACRUM | 0:276e7a263c35 | 618 | * @details This call is responsible for initiating the process for |
| MACRUM | 0:276e7a263c35 | 619 | * applying a new/different image. Depending on the platform this |
| MACRUM | 0:276e7a263c35 | 620 | * could be: |
| MACRUM | 0:276e7a263c35 | 621 | * * An empty call, if the installer can deduce which slot to |
| MACRUM | 0:276e7a263c35 | 622 | * choose from based on the firmware details. |
| MACRUM | 0:276e7a263c35 | 623 | * * Setting a flag to indicate which slot to use next. |
| MACRUM | 0:276e7a263c35 | 624 | * * Decompressing/decrypting/installing the firmware image on |
| MACRUM | 0:276e7a263c35 | 625 | * top of another. |
| MACRUM | 0:276e7a263c35 | 626 | * |
| MACRUM | 0:276e7a263c35 | 627 | * @param location Storage location ID. |
| MACRUM | 0:276e7a263c35 | 628 | * @return Returns ERR_NONE on accept, and signals the event handler with |
| MACRUM | 0:276e7a263c35 | 629 | * either DONE or ERROR when complete. |
| MACRUM | 0:276e7a263c35 | 630 | * Returns ERR_INVALID_PARAMETER on reject, and no signal is sent. |
| MACRUM | 0:276e7a263c35 | 631 | */ |
| MACRUM | 0:276e7a263c35 | 632 | arm_uc_error_t ARM_UC_PAL_RTL8195AM_Activate(uint32_t location) |
| MACRUM | 0:276e7a263c35 | 633 | { |
| MACRUM | 0:276e7a263c35 | 634 | arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER }; |
| MACRUM | 0:276e7a263c35 | 635 | |
| MACRUM | 0:276e7a263c35 | 636 | UC_PAAL_TRACE("Activate"); |
| MACRUM | 0:276e7a263c35 | 637 | |
| MACRUM | 0:276e7a263c35 | 638 | uint8_t buffer[HEADER_SIZE] = { 0 }; |
| MACRUM | 0:276e7a263c35 | 639 | |
| MACRUM | 0:276e7a263c35 | 640 | int status = arm_uc_flashiap_read(buffer, arm_uc_base_address, sizeof(buffer)); |
| MACRUM | 0:276e7a263c35 | 641 | |
| MACRUM | 0:276e7a263c35 | 642 | if (status == 0) |
| MACRUM | 0:276e7a263c35 | 643 | { |
| MACRUM | 0:276e7a263c35 | 644 | /* calculate CRC */ |
| MACRUM | 0:276e7a263c35 | 645 | uint32_t crc = arm_uc_crc32(buffer, OTA_CRC32_OFS); |
| MACRUM | 0:276e7a263c35 | 646 | |
| MACRUM | 0:276e7a263c35 | 647 | buffer[0] = crc & 0xFF; |
| MACRUM | 0:276e7a263c35 | 648 | buffer[1] = (crc >> 8) & 0xFF; |
| MACRUM | 0:276e7a263c35 | 649 | buffer[2] = (crc >> 16) & 0xFF; |
| MACRUM | 0:276e7a263c35 | 650 | buffer[3] = (crc >> 24) & 0xFF; |
| MACRUM | 0:276e7a263c35 | 651 | |
| MACRUM | 0:276e7a263c35 | 652 | /* set crc in header to signal the bootloader that the image is ready */ |
| MACRUM | 0:276e7a263c35 | 653 | status = arm_uc_flashiap_program(buffer, arm_uc_base_address + OTA_CRC32_OFS, 4); |
| MACRUM | 0:276e7a263c35 | 654 | |
| MACRUM | 0:276e7a263c35 | 655 | if (status == 0) |
| MACRUM | 0:276e7a263c35 | 656 | { |
| MACRUM | 0:276e7a263c35 | 657 | /* set return code */ |
| MACRUM | 0:276e7a263c35 | 658 | result.code = ERR_NONE; |
| MACRUM | 0:276e7a263c35 | 659 | |
| MACRUM | 0:276e7a263c35 | 660 | /* signal done */ |
| MACRUM | 0:276e7a263c35 | 661 | arm_uc_pal_rtl8195am_signal_internal(ARM_UC_PAAL_EVENT_ACTIVATE_DONE); |
| MACRUM | 0:276e7a263c35 | 662 | } |
| MACRUM | 0:276e7a263c35 | 663 | } |
| MACRUM | 0:276e7a263c35 | 664 | |
| MACRUM | 0:276e7a263c35 | 665 | return result; |
| MACRUM | 0:276e7a263c35 | 666 | } |
| MACRUM | 0:276e7a263c35 | 667 | |
| MACRUM | 0:276e7a263c35 | 668 | /** |
| MACRUM | 0:276e7a263c35 | 669 | * @brief Get firmware details for the firmware image in the slot passed. |
| MACRUM | 0:276e7a263c35 | 670 | * @details This call populates the passed details struct with information |
| MACRUM | 0:276e7a263c35 | 671 | * about the firmware image in the slot passed. Only the fields |
| MACRUM | 0:276e7a263c35 | 672 | * marked as supported in the capabilities bitmap will have valid |
| MACRUM | 0:276e7a263c35 | 673 | * values. |
| MACRUM | 0:276e7a263c35 | 674 | * |
| MACRUM | 0:276e7a263c35 | 675 | * @param details Pointer to firmware details struct to be populated. |
| MACRUM | 0:276e7a263c35 | 676 | * @return Returns ERR_NONE on accept, and signals the event handler with |
| MACRUM | 0:276e7a263c35 | 677 | * either DONE or ERROR when complete. |
| MACRUM | 0:276e7a263c35 | 678 | * Returns ERR_INVALID_PARAMETER on reject, and no signal is sent. |
| MACRUM | 0:276e7a263c35 | 679 | */ |
| MACRUM | 0:276e7a263c35 | 680 | arm_uc_error_t ARM_UC_PAL_RTL8195AM_GetFirmwareDetails( |
| MACRUM | 0:276e7a263c35 | 681 | uint32_t location, |
| MACRUM | 0:276e7a263c35 | 682 | arm_uc_firmware_details_t* details) |
| MACRUM | 0:276e7a263c35 | 683 | { |
| MACRUM | 0:276e7a263c35 | 684 | arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER }; |
| MACRUM | 0:276e7a263c35 | 685 | |
| MACRUM | 0:276e7a263c35 | 686 | /* this function is only used by the mbed Bootloader */ |
| MACRUM | 0:276e7a263c35 | 687 | |
| MACRUM | 0:276e7a263c35 | 688 | return result; |
| MACRUM | 0:276e7a263c35 | 689 | } |
| MACRUM | 0:276e7a263c35 | 690 | |
| MACRUM | 0:276e7a263c35 | 691 | /*****************************************************************************/ |
| MACRUM | 0:276e7a263c35 | 692 | |
| MACRUM | 0:276e7a263c35 | 693 | arm_uc_error_t ARM_UC_PAL_RTL8195AM_GetActiveDetails(arm_uc_firmware_details_t* details) |
| MACRUM | 0:276e7a263c35 | 694 | { |
| MACRUM | 0:276e7a263c35 | 695 | arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER }; |
| MACRUM | 0:276e7a263c35 | 696 | |
| MACRUM | 0:276e7a263c35 | 697 | if (details) |
| MACRUM | 0:276e7a263c35 | 698 | { |
| MACRUM | 0:276e7a263c35 | 699 | UC_PAAL_TRACE("GetActiveDetails"); |
| MACRUM | 0:276e7a263c35 | 700 | |
| MACRUM | 0:276e7a263c35 | 701 | /* find running slot */ |
| MACRUM | 0:276e7a263c35 | 702 | uint32_t base_address = arm_uc_pal_find_base_address(BASE_ADDRESS_RUNNING); |
| MACRUM | 0:276e7a263c35 | 703 | |
| MACRUM | 0:276e7a263c35 | 704 | UC_PAAL_TRACE("active base: %" PRIX32, base_address); |
| MACRUM | 0:276e7a263c35 | 705 | |
| MACRUM | 0:276e7a263c35 | 706 | result = arm_uc_pal_get_realtek_header(base_address, details); |
| MACRUM | 0:276e7a263c35 | 707 | |
| MACRUM | 0:276e7a263c35 | 708 | /* signal event if operation was successful */ |
| MACRUM | 0:276e7a263c35 | 709 | if (result.error == ERR_NONE) |
| MACRUM | 0:276e7a263c35 | 710 | { |
| MACRUM | 0:276e7a263c35 | 711 | arm_uc_pal_rtl8195am_signal_internal(ARM_UC_PAAL_EVENT_GET_ACTIVE_FIRMWARE_DETAILS_DONE); |
| MACRUM | 0:276e7a263c35 | 712 | } |
| MACRUM | 0:276e7a263c35 | 713 | } |
| MACRUM | 0:276e7a263c35 | 714 | |
| MACRUM | 0:276e7a263c35 | 715 | return result; |
| MACRUM | 0:276e7a263c35 | 716 | } |
| MACRUM | 0:276e7a263c35 | 717 | |
| MACRUM | 0:276e7a263c35 | 718 | arm_uc_error_t ARM_UC_PAL_RTL8195AM_GetInstallerDetails(arm_uc_installer_details_t* details) |
| MACRUM | 0:276e7a263c35 | 719 | { |
| MACRUM | 0:276e7a263c35 | 720 | arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER }; |
| MACRUM | 0:276e7a263c35 | 721 | |
| MACRUM | 0:276e7a263c35 | 722 | if (details) |
| MACRUM | 0:276e7a263c35 | 723 | { |
| MACRUM | 0:276e7a263c35 | 724 | /* reset installer details struct */ |
| MACRUM | 0:276e7a263c35 | 725 | memset(&details->arm_hash, 0, ARM_UC_SHA256_SIZE); |
| MACRUM | 0:276e7a263c35 | 726 | memset(&details->oem_hash, 0, ARM_UC_SHA256_SIZE); |
| MACRUM | 0:276e7a263c35 | 727 | details->layout = 0; |
| MACRUM | 0:276e7a263c35 | 728 | |
| MACRUM | 0:276e7a263c35 | 729 | /* the magic tag identifies the bootloader it is compatible with */ |
| MACRUM | 0:276e7a263c35 | 730 | details->oem_hash[0] = (OTA_TAG_ID >> 24) & 0xFF; |
| MACRUM | 0:276e7a263c35 | 731 | details->oem_hash[1] = (OTA_TAG_ID >> 16) & 0xFF; |
| MACRUM | 0:276e7a263c35 | 732 | details->oem_hash[2] = (OTA_TAG_ID >> 8) & 0xFF; |
| MACRUM | 0:276e7a263c35 | 733 | details->oem_hash[3] = OTA_TAG_ID & 0xFF; |
| MACRUM | 0:276e7a263c35 | 734 | |
| MACRUM | 0:276e7a263c35 | 735 | details->oem_hash[4] = (OTA_VER_ID >> 24) & 0xFF; |
| MACRUM | 0:276e7a263c35 | 736 | details->oem_hash[5] = (OTA_VER_ID >> 16) & 0xFF; |
| MACRUM | 0:276e7a263c35 | 737 | details->oem_hash[6] = (OTA_VER_ID >> 8) & 0xFF; |
| MACRUM | 0:276e7a263c35 | 738 | details->oem_hash[7] = OTA_VER_ID & 0xFF; |
| MACRUM | 0:276e7a263c35 | 739 | |
| MACRUM | 0:276e7a263c35 | 740 | result.code = ERR_NONE; |
| MACRUM | 0:276e7a263c35 | 741 | |
| MACRUM | 0:276e7a263c35 | 742 | arm_uc_pal_rtl8195am_signal_internal(ARM_UC_PAAL_EVENT_GET_INSTALLER_DETAILS_DONE); |
| MACRUM | 0:276e7a263c35 | 743 | } |
| MACRUM | 0:276e7a263c35 | 744 | |
| MACRUM | 0:276e7a263c35 | 745 | return result; |
| MACRUM | 0:276e7a263c35 | 746 | } |
| MACRUM | 0:276e7a263c35 | 747 | |
| MACRUM | 0:276e7a263c35 | 748 | ARM_UC_PAAL_UPDATE_CAPABILITIES ARM_UC_PAL_RTL8195AM_GetCapabilities(void) |
| MACRUM | 0:276e7a263c35 | 749 | { |
| MACRUM | 0:276e7a263c35 | 750 | ARM_UC_PAAL_UPDATE_CAPABILITIES result = { |
| MACRUM | 0:276e7a263c35 | 751 | .installer_arm_hash = 0, |
| MACRUM | 0:276e7a263c35 | 752 | .installer_oem_hash = 0, |
| MACRUM | 0:276e7a263c35 | 753 | .installer_layout = 0, |
| MACRUM | 0:276e7a263c35 | 754 | .firmware_hash = 1, |
| MACRUM | 0:276e7a263c35 | 755 | .firmware_hmac = 0, |
| MACRUM | 0:276e7a263c35 | 756 | .firmware_campaign = 0, |
| MACRUM | 0:276e7a263c35 | 757 | .firmware_version = 1, |
| MACRUM | 0:276e7a263c35 | 758 | .firmware_size = 1 |
| MACRUM | 0:276e7a263c35 | 759 | }; |
| MACRUM | 0:276e7a263c35 | 760 | |
| MACRUM | 0:276e7a263c35 | 761 | return result; |
| MACRUM | 0:276e7a263c35 | 762 | } |
| MACRUM | 0:276e7a263c35 | 763 | |
| MACRUM | 0:276e7a263c35 | 764 | const ARM_UC_PAAL_UPDATE ARM_UCP_REALTEK_RTL8195AM = |
| MACRUM | 0:276e7a263c35 | 765 | { |
| MACRUM | 0:276e7a263c35 | 766 | .Initialize = ARM_UC_PAL_RTL8195AM_Initialize, |
| MACRUM | 0:276e7a263c35 | 767 | .GetCapabilities = ARM_UC_PAL_RTL8195AM_GetCapabilities, |
| MACRUM | 0:276e7a263c35 | 768 | .GetMaxID = ARM_UC_PAL_RTL8195AM_GetMaxID, |
| MACRUM | 0:276e7a263c35 | 769 | .Prepare = ARM_UC_PAL_RTL8195AM_Prepare, |
| MACRUM | 0:276e7a263c35 | 770 | .Write = ARM_UC_PAL_RTL8195AM_Write, |
| MACRUM | 0:276e7a263c35 | 771 | .Finalize = ARM_UC_PAL_RTL8195AM_Finalize, |
| MACRUM | 0:276e7a263c35 | 772 | .Read = ARM_UC_PAL_RTL8195AM_Read, |
| MACRUM | 0:276e7a263c35 | 773 | .Activate = ARM_UC_PAL_RTL8195AM_Activate, |
| MACRUM | 0:276e7a263c35 | 774 | .GetActiveFirmwareDetails = ARM_UC_PAL_RTL8195AM_GetActiveDetails, |
| MACRUM | 0:276e7a263c35 | 775 | .GetFirmwareDetails = ARM_UC_PAL_RTL8195AM_GetFirmwareDetails, |
| MACRUM | 0:276e7a263c35 | 776 | .GetInstallerDetails = ARM_UC_PAL_RTL8195AM_GetInstallerDetails |
| MACRUM | 0:276e7a263c35 | 777 | }; |
| MACRUM | 0:276e7a263c35 | 778 | |
| MACRUM | 0:276e7a263c35 | 779 | #endif |