/*********************************************************************
 * @fn      SNP_RPC_stAuthenticationData
 *
 * @brief   Set the Authentication data for a pairing procedure.
 *
 * @param   pReq - pointer to SPN request message
 *
 * @return  uint8_t - status of this command
 */
uint8_t SNP_RPC_setAuthenticationData(snpSetAuthDataReq_t *pReq)
{
  snpSetAuthDataRsp_t rsp;
  _npiFrame_t *pPkt;
  uint8_t *ptr;
  uint8_t status = SNP_OUT_OF_RESOURCES;

  // Allocated an empty data NPI packet.
  pPkt = SNP_buildNPIPacket(SNP_NPI_SYNC_REQ_TYPE,
                            SNP_SET_AUTHENTICATION_DATA_REQ, 4);

  if ( pPkt )
  {
    status = SNP_SUCCESS;

    ptr = pPkt->pData;
    UINT32_TO_BUF_LITTLE_ENDIAN(ptr, pReq->authData);

    // Send a synchronous command.
    SNP_sendSynchronousCmd(pPkt, SNP_SET_AUTHENTICATION_DATA_REQ,
                           (snp_msg_t *)&rsp, NULL);

    status = rsp.status;
  }

  // Return Status
  return status;
}
Example #2
0
/**************************************************************************************************
 * @fn          sbResp
 *
 * @brief       Make the SB response.
 *
 * input parameters
 *
 * @param       sbCmd - the command to respond to
 * @param       rsp - The byte code response to send.
 * @param       len - The data length of the response.
 *
 * output parameters
 *
 * None.
 *
 * @return      None.
 **************************************************************************************************
 */
static void sbResp(uint8 sbCmd, uint8 rsp, uint32 payloadLen)
{
    uint8         fcs = 0;
    uint8         headerBuf[10];
    uint8         * pBuf = headerBuf;
    /* Include the payload len + one byte for rsp */
    uint32        reportedLen;
    uint32        headerLen;
    uint32        i;

    reportedLen = payloadLen + 1;

    *pBuf++ = SB_SOF;
    if (reportedLen < 0xFF)
    {
        *pBuf++ = (uint8)(reportedLen & 0xFF);
    }
    else
    {
        *pBuf++ = 0xFF;
    }
    *pBuf++ = SB_RPC_SYS_BOOT;

    /* The MSB of the command field is set, to mark that this is a reply */
    *pBuf++ = sbCmd | 0x80;
    if (reportedLen >= 0xFF)
    {
        UINT32_TO_BUF_LITTLE_ENDIAN(pBuf, reportedLen);
    }
    *pBuf++ = rsp;

    headerLen = pBuf - headerBuf;

    /* Calculate the fcs. The SOF char is not part of the checksum */
    for (i = 1; i < headerLen; i++)
    {
        fcs ^= headerBuf[i];
    }

    for (i = 0; i < payloadLen; i++)
    {
        fcs ^= sbBuf[i];
    }
    sbBuf[payloadLen] = fcs;

    pBuf = (uint8 *)sbBuf - headerLen;
    memcpy(pBuf, headerBuf, headerLen);

    sbTx(pBuf, (headerLen + payloadLen + 1 ));
}
Example #3
0
/**************************************************************************************************
 * @fn          sbResp
 *
 * @brief       Make the SB response.
 *
 * input parameters
 *
 * @param       sbCmd - the command to respond to
 * @param       rsp - The byte code response to send.
 * @param       payload_len - The data length of the response.
 *
 * output parameters
 *
 * None.
 *
 * @return      None.
 */
static void sbResp(uint8 sbCmd, uint8 rsp, uint32 payload_len)
{
  uint8 fcs = 0;
  uint8 headerBuf[10];
  uint8 * pBuf = headerBuf;
  uint32 reported_len; // Include the payload len + one byte for rsp
  uint32 header_len;
  uint32 i;
  
  reported_len = payload_len + 1; 
  
  *pBuf++ = SB_SOF;
  if (reported_len < 0xFF)
  {
    *pBuf++ = (uint8)(reported_len & 0xFF);
  }
  else
  {
    *pBuf++ = 0xFF;
  }
  *pBuf++ = SB_RPC_SYS_BOOT;

  // The MSB of the command field is set, to mark that this is a reply
  *pBuf++ = sbCmd | 0x80;
  if (reported_len >= 0xFF)
  {
    UINT32_TO_BUF_LITTLE_ENDIAN(pBuf, reported_len);
  }
  *pBuf++ = rsp;
  
  header_len = pBuf - headerBuf;
  
  // Caluclate the fcs
  for (i = 1; i < header_len; i++) // The SOF char is not part of the checksum
  {
    fcs ^= headerBuf[i];
  }
  
  for (i = 0; i < payload_len; i++)
  {
    fcs ^= sbBuf[i];
  }
  
  while (SB_TX(headerBuf, header_len) == 0);
  if (payload_len > 0)
  {
    while (SB_TX(sbBuf, payload_len) == 0);
  }
  while (SB_TX(&fcs, 1) == 0);
}
Example #4
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;
}