Esempio n. 1
0
/**************************************************************************************************
 * @fn          sbCmnd
 *
 * @brief       Act on the SB command and received buffer.
 *
 * input parameters
 *
 * @param 		sbCmd - Received SBL command.
 * @param		payload_len - Length of command payload
 *
 * output parameters
 *
 * None.
 *
 * @return      TRUE to indicate that the SB_ENABLE_CMD command was successful; FALSE otherwise.
 **************************************************************************************************
 */
static uint8 sbCmnd(uint8 sbCmd, uint32 payload_len)
{
    uint32        firstAddr;
    uint32        lastAddr;
    uint32        operationLength;
    uint32        writeLength;
    uint32        respPayloadLen = 0;
    uint32        pageNumber;
    uint32        i;
    uint32        actual_number_of_data_bytes_to_send;
    uint8         paddingLength;
    uint8         rsp = SB_SUCCESS;
    uint8         imageEnabledSuccessfully = FALSE;
    uint8         *pBuf;

    pBuf = sbBuf;

    switch (sbCmd)
    {
    case SB_HANDSHAKE_CMD:
        /* Mark all pages as not-deleted-yet */
        memset(pageDeleted, 0, sizeof(pageDeleted));

        UINT32_TO_BUF_LITTLE_ENDIAN(pBuf, SB_BOOTLOADER_REVISION);
        *pBuf++ = SB_DEVICE_TYPE_2538;
        UINT32_TO_BUF_LITTLE_ENDIAN(pBuf, SB_RW_BUF_LEN );
        UINT32_TO_BUF_LITTLE_ENDIAN(pBuf, SB_DEVICE_PAGE_SIZE);
        respPayloadLen = pBuf - sbBuf;
        break;

    case SB_WRITE_CMD:
        firstAddr = BUF_TO_UINT32_LITTLE_ENDIAN(pBuf);
        operationLength = BUF_TO_UINT32_LITTLE_ENDIAN(pBuf);

        /* The payload_len includes the addr_offset
         * and the operationLength fields. The value
         * (pBuf - sbBuf) gives the number of bytes
         * used by those firelds. The remaining bytes
         *  are the actual data bytes to be written.
         */
        writeLength = payload_len - (pBuf - sbBuf);
        lastAddr = firstAddr + operationLength - 1;
        if ((firstAddr < FLASH_BASE) ||
                (lastAddr > CC2538_CODE_FLASH_END_ADDRESS) ||
                (writeLength > operationLength))
        {
            rsp = SB_FAILURE;
            break;
        }

        /* Before writing to a flash page for the first time during a bootloading session, the
         * page must be erased. The following section makes sure that every page being written
         * to have already been erased, otherwise, it erases it (before writing to it).
         * Note that the write command may span over more than a single page.
         */
        for (pageNumber = GET_PAGE_NUMBER(firstAddr); pageNumber <= GET_PAGE_NUMBER(lastAddr); pageNumber++)
        {
            if (!IS_PAGE_ERASED(pageNumber))
            {
                if (FlashMainPageErase(GET_PAGE_ADDRESS(pageNumber)) != 0)
                {
                    rsp = SB_FAILURE;
                    break;
                }

                MARK_PAGE_ERASED(pageNumber);
            }
        }

        /* Note that the start address (firstAddr) and the byte count (writeLength) must be
         * word aligned. The start address is expected to be already aligned (by the SBL server),
         * since aligning it here would require padding the buffer's start, which would require
         * shifting the buffer content (as the buffer is passesd as (uint32_t *pui32Data) so it
         * should be aligned by itself. The byte count is aligned below.
         */
        paddingLength = ((4 - (writeLength & 0x00000003)) % 4);
        for (i = 0; i < paddingLength; i++)
        {
            pBuf[writeLength + i] = 0xFF;
        }
        writeLength += paddingLength;


        /* If the page was successfully erased (or was previously erased), perform the write action.
         * Note that pBuf must point to a uint32-aligned address, as required by FlashMainPageProgram().
         * This is the case now (the prefixing field are total of 8 bytes), and _sbBuf is 32bit aligned.
         */
        if ((rsp == SB_SUCCESS) && (writeLength > 0) &&
                (FlashMainPageProgram((uint32_t *)(pBuf), firstAddr, writeLength) != 0))
        {
            rsp = SB_FAILURE;
        }

        break;

    case SB_READ_CMD:
        firstAddr = BUF_TO_UINT32_LITTLE_ENDIAN(pBuf);
        operationLength = BUF_TO_UINT32_LITTLE_ENDIAN(pBuf);
        lastAddr = firstAddr + operationLength - 1;

        if ((firstAddr < FLASH_BASE) ||
                (lastAddr > CC2538_CODE_FLASH_END_ADDRESS) ||
                (operationLength > sizeof(_sbBuf)))
        {
            rsp = SB_FAILURE;
            break;
        }

#if !MT_SYS_OSAL_NV_READ_CERTIFICATE_DATA
#if (HAL_IMG_A_BEG > HAL_NV_START_ADDR)
#warning This check assumes NV PAGES located at the end of the program flash memory
#endif
        if (GET_PAGE_NUMBER(lastAddr) >= HAL_NV_PAGE_BEG)
        {
            rsp = SB_FAILURE;
            break;
        }
#endif

        /* If the end of the buffer is made only of 0xFF characters, no need to
         *  send them. Find out the number of bytes that needs to be sent:
         */
        for (actual_number_of_data_bytes_to_send = operationLength;
                (actual_number_of_data_bytes_to_send > 0) && ((*(uint8 *)(firstAddr + actual_number_of_data_bytes_to_send - 1)) == 0xFF);
                actual_number_of_data_bytes_to_send--);

        /* As a future upgrade, memcopy can be avoided. Instead,
         * may pass a pointer to the actual flash address
         */
        (void)memcpy(pBuf, (const void *)firstAddr, actual_number_of_data_bytes_to_send);
        respPayloadLen = (pBuf - sbBuf) + actual_number_of_data_bytes_to_send;
        break;

    case SB_ENABLE_CMD:
        if (enableImg())
        {
            imageEnabledSuccessfully = TRUE;
        }
        else
        {
            rsp = SB_VALIDATE_FAILED;
        }
        break;

    default:
        break;
    }

    sbResp(sbCmd, rsp, respPayloadLen);
    return imageEnabledSuccessfully;
}
Esempio n. 2
0
/**************************************************************************************************
 * @fn          sbCmnd
 *
 * @brief       Act on the SB command and received buffer.
 *
 * input parameters
 *
 * None.
 *
 * output parameters
 *
 * None.
 *
 * @return      TRUE to indicate that the SB_ENABLE_CMD command was successful; FALSE otherwise.
 **************************************************************************************************
 */
static uint8 sbCmnd(void)
{
  uint16 tmp = BUILD_UINT16(sbBuf[SB_DATA_STATE], sbBuf[SB_DATA_STATE+1]) + SB_IMG_OSET;
  uint16 crc[2];
  uint8 len = 1;
  uint8 rsp = SB_SUCCESS;
  uint8 rtrn = FALSE;

  switch (sbCmd2)
  {
  case SB_HANDSHAKE_CMD:
    break;

  case SB_WRITE_CMD:
    if ((tmp % SB_WPG_SIZE) == 0)
    {
      HalFlashErase(tmp / SB_WPG_SIZE);
    }

    HalFlashWrite(tmp, sbBuf+SB_DATA_STATE+2, SB_RW_BUF_LEN / HAL_FLASH_WORD_SIZE);
    break;

  case SB_READ_CMD:
#if !MT_SYS_OSAL_NV_READ_CERTIFICATE_DATA
    if ((tmp / (HAL_FLASH_PAGE_SIZE / 4)) >= HAL_NV_PAGE_BEG)
    {
      rsp = SB_FAILURE;
      break;
    }
#endif
    HalFlashRead(tmp / (HAL_FLASH_PAGE_SIZE / 4),
                 (tmp % (HAL_FLASH_PAGE_SIZE / 4)) << 2,
                 sbBuf + SB_DATA_STATE + 3, SB_RW_BUF_LEN);
    sbBuf[SB_DATA_STATE+2] = sbBuf[SB_DATA_STATE+1];
    sbBuf[SB_DATA_STATE+1] = sbBuf[SB_DATA_STATE];
    len = SB_RW_BUF_LEN + 3;
    break;
  
  case SB_ENABLE_CMD:
    HalFlashRead(HAL_SB_CRC_ADDR / HAL_FLASH_PAGE_SIZE,
                 HAL_SB_CRC_ADDR % HAL_FLASH_PAGE_SIZE,
                 (uint8 *)crc, sizeof(crc));

    // Bootload master must have verified extra checks to be issuing the SB_ENABLE_CMD.
    //if ((crc[0] != crc[1]) && (crc[0] != 0xFFFF) && (crc[0] != 0x0000))
    if (crc[1] != crc[0])
    {
      crc[1] = crc[0];
      HalFlashWrite((HAL_SB_CRC_ADDR / HAL_FLASH_WORD_SIZE), (uint8 *)crc, 1);
      HalFlashRead(  HAL_SB_CRC_ADDR / HAL_FLASH_PAGE_SIZE,
                     HAL_SB_CRC_ADDR % HAL_FLASH_PAGE_SIZE,
                     (uint8 *)crc, sizeof(crc));
    }

    // Bootload master must have verified extra checks to be issuing the SB_ENABLE_CMD.
    //if ((crc[0] == crc[1]) && (crc[0] != 0xFFFF) && (crc[0] != 0x0000))
    if (crc[0] == crc[1])
    {
      rtrn = TRUE;
    }
    else
    {
      rsp = SB_VALIDATE_FAILED;
    }
    break;
    
  default:
    break;
  }
  
  sbResp(rsp, len);
  return rtrn;
}