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