Simple interface for Mbed Cloud Client
Embed:
(wiki syntax)
Show/hide line numbers
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. buffer->size 00564 * contains the intended read size. 00565 * @return Returns ERR_NONE on accept, and signals the event handler with 00566 * either DONE or ERROR when complete. 00567 * Returns ERR_INVALID_PARAMETER on reject, and no signal is sent. 00568 * buffer->size contains actual bytes read on return. 00569 */ 00570 arm_uc_error_t ARM_UC_PAL_RTL8195AM_Read(uint32_t location, 00571 uint32_t offset, 00572 arm_uc_buffer_t* buffer) 00573 { 00574 arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER }; 00575 00576 if (buffer && buffer->ptr) 00577 { 00578 /* find the base address for the spare slot if not already set */ 00579 if (arm_uc_base_address == 0) 00580 { 00581 arm_uc_base_address = arm_uc_pal_find_base_address(BASE_ADDRESS_SPARE); 00582 } 00583 00584 /* calculate actual physical address */ 00585 uint32_t physical_address = arm_uc_base_address + HEADER_SIZE + offset; 00586 00587 UC_PAAL_TRACE("Read: %" PRIX32 " %" PRIX32 " %" PRIX32, 00588 physical_address, 00589 offset, 00590 buffer->size); 00591 00592 uint32_t read_size = buffer->size; 00593 00594 int status = arm_uc_flashiap_read(buffer->ptr, physical_address, read_size); 00595 00596 if (status == 0) 00597 { 00598 /* set buffer size */ 00599 buffer->size = read_size; 00600 00601 /* set return code */ 00602 result.code = ERR_NONE; 00603 00604 /* signal done */ 00605 arm_uc_pal_rtl8195am_signal_internal(ARM_UC_PAAL_EVENT_READ_DONE); 00606 } 00607 else 00608 { 00609 UC_PAAL_ERR_MSG("flash read failed"); 00610 } 00611 } 00612 00613 return result; 00614 } 00615 00616 /** 00617 * @brief Set the firmware image in the slot to be the new active image. 00618 * @details This call is responsible for initiating the process for 00619 * applying a new/different image. Depending on the platform this 00620 * could be: 00621 * * An empty call, if the installer can deduce which slot to 00622 * choose from based on the firmware details. 00623 * * Setting a flag to indicate which slot to use next. 00624 * * Decompressing/decrypting/installing the firmware image on 00625 * top of another. 00626 * 00627 * @param location Storage location ID. 00628 * @return Returns ERR_NONE on accept, and signals the event handler with 00629 * either DONE or ERROR when complete. 00630 * Returns ERR_INVALID_PARAMETER on reject, and no signal is sent. 00631 */ 00632 arm_uc_error_t ARM_UC_PAL_RTL8195AM_Activate(uint32_t location) 00633 { 00634 arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER }; 00635 00636 UC_PAAL_TRACE("Activate"); 00637 00638 uint8_t buffer[HEADER_SIZE] = { 0 }; 00639 00640 int status = arm_uc_flashiap_read(buffer, arm_uc_base_address, sizeof(buffer)); 00641 00642 if (status == 0) 00643 { 00644 /* calculate CRC */ 00645 uint32_t crc = arm_uc_crc32(buffer, OTA_CRC32_OFS); 00646 00647 buffer[0] = crc & 0xFF; 00648 buffer[1] = (crc >> 8) & 0xFF; 00649 buffer[2] = (crc >> 16) & 0xFF; 00650 buffer[3] = (crc >> 24) & 0xFF; 00651 00652 /* set crc in header to signal the bootloader that the image is ready */ 00653 status = arm_uc_flashiap_program(buffer, arm_uc_base_address + OTA_CRC32_OFS, 4); 00654 00655 if (status == 0) 00656 { 00657 /* set return code */ 00658 result.code = ERR_NONE; 00659 00660 /* signal done */ 00661 arm_uc_pal_rtl8195am_signal_internal(ARM_UC_PAAL_EVENT_ACTIVATE_DONE); 00662 } 00663 } 00664 00665 return result; 00666 } 00667 00668 /** 00669 * @brief Get firmware details for the firmware image in the slot passed. 00670 * @details This call populates the passed details struct with information 00671 * about the firmware image in the slot passed. Only the fields 00672 * marked as supported in the capabilities bitmap will have valid 00673 * values. 00674 * 00675 * @param details Pointer to firmware details struct to be populated. 00676 * @return Returns ERR_NONE on accept, and signals the event handler with 00677 * either DONE or ERROR when complete. 00678 * Returns ERR_INVALID_PARAMETER on reject, and no signal is sent. 00679 */ 00680 arm_uc_error_t ARM_UC_PAL_RTL8195AM_GetFirmwareDetails( 00681 uint32_t location, 00682 arm_uc_firmware_details_t* details) 00683 { 00684 arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER }; 00685 00686 /* this function is only used by the mbed Bootloader */ 00687 00688 return result; 00689 } 00690 00691 /*****************************************************************************/ 00692 00693 arm_uc_error_t ARM_UC_PAL_RTL8195AM_GetActiveDetails(arm_uc_firmware_details_t* details) 00694 { 00695 arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER }; 00696 00697 if (details) 00698 { 00699 UC_PAAL_TRACE("GetActiveDetails"); 00700 00701 /* find running slot */ 00702 uint32_t base_address = arm_uc_pal_find_base_address(BASE_ADDRESS_RUNNING); 00703 00704 UC_PAAL_TRACE("active base: %" PRIX32, base_address); 00705 00706 result = arm_uc_pal_get_realtek_header(base_address, details); 00707 00708 /* signal event if operation was successful */ 00709 if (result.error == ERR_NONE) 00710 { 00711 arm_uc_pal_rtl8195am_signal_internal(ARM_UC_PAAL_EVENT_GET_ACTIVE_FIRMWARE_DETAILS_DONE); 00712 } 00713 } 00714 00715 return result; 00716 } 00717 00718 arm_uc_error_t ARM_UC_PAL_RTL8195AM_GetInstallerDetails(arm_uc_installer_details_t* details) 00719 { 00720 arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER }; 00721 00722 if (details) 00723 { 00724 /* reset installer details struct */ 00725 memset(&details->arm_hash, 0, ARM_UC_SHA256_SIZE); 00726 memset(&details->oem_hash, 0, ARM_UC_SHA256_SIZE); 00727 details->layout = 0; 00728 00729 /* the magic tag identifies the bootloader it is compatible with */ 00730 details->oem_hash[0] = (OTA_TAG_ID >> 24) & 0xFF; 00731 details->oem_hash[1] = (OTA_TAG_ID >> 16) & 0xFF; 00732 details->oem_hash[2] = (OTA_TAG_ID >> 8) & 0xFF; 00733 details->oem_hash[3] = OTA_TAG_ID & 0xFF; 00734 00735 details->oem_hash[4] = (OTA_VER_ID >> 24) & 0xFF; 00736 details->oem_hash[5] = (OTA_VER_ID >> 16) & 0xFF; 00737 details->oem_hash[6] = (OTA_VER_ID >> 8) & 0xFF; 00738 details->oem_hash[7] = OTA_VER_ID & 0xFF; 00739 00740 result.code = ERR_NONE; 00741 00742 arm_uc_pal_rtl8195am_signal_internal(ARM_UC_PAAL_EVENT_GET_INSTALLER_DETAILS_DONE); 00743 } 00744 00745 return result; 00746 } 00747 00748 ARM_UC_PAAL_UPDATE_CAPABILITIES ARM_UC_PAL_RTL8195AM_GetCapabilities(void) 00749 { 00750 ARM_UC_PAAL_UPDATE_CAPABILITIES result = { 00751 .installer_arm_hash = 0, 00752 .installer_oem_hash = 0, 00753 .installer_layout = 0, 00754 .firmware_hash = 1, 00755 .firmware_hmac = 0, 00756 .firmware_campaign = 0, 00757 .firmware_version = 1, 00758 .firmware_size = 1 00759 }; 00760 00761 return result; 00762 } 00763 00764 const ARM_UC_PAAL_UPDATE ARM_UCP_REALTEK_RTL8195AM = 00765 { 00766 .Initialize = ARM_UC_PAL_RTL8195AM_Initialize, 00767 .GetCapabilities = ARM_UC_PAL_RTL8195AM_GetCapabilities, 00768 .GetMaxID = ARM_UC_PAL_RTL8195AM_GetMaxID, 00769 .Prepare = ARM_UC_PAL_RTL8195AM_Prepare, 00770 .Write = ARM_UC_PAL_RTL8195AM_Write, 00771 .Finalize = ARM_UC_PAL_RTL8195AM_Finalize, 00772 .Read = ARM_UC_PAL_RTL8195AM_Read, 00773 .Activate = ARM_UC_PAL_RTL8195AM_Activate, 00774 .GetActiveFirmwareDetails = ARM_UC_PAL_RTL8195AM_GetActiveDetails, 00775 .GetFirmwareDetails = ARM_UC_PAL_RTL8195AM_GetFirmwareDetails, 00776 .GetInstallerDetails = ARM_UC_PAL_RTL8195AM_GetInstallerDetails 00777 }; 00778 00779 #endif
Generated on Tue Jul 12 2022 19:01:33 by 1.7.2