Maxim Integrated / Mbed OS MAXREFDES220#

Dependencies:   USBDevice max32630fthr

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers SSBootloaderComm.cpp Source File

SSBootloaderComm.cpp

00001 /*******************************************************************************
00002  * Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
00003  *
00004  * Permission is hereby granted, free of charge, to any person obtaining a
00005  * copy of this software and associated documentation files (the "Software"),
00006  * to deal in the Software without restriction, including without limitation
00007  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
00008  * and/or sell copies of the Software, and to permit persons to whom the
00009  * Software is furnished to do so, subject to the following conditions:
00010  *
00011  * The above copyright notice and this permission notice shall be included
00012  * in all copies or substantial portions of the Software.
00013  *
00014  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
00015  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00016  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
00017  * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
00018  * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
00019  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
00020  * OTHER DEALINGS IN THE SOFTWARE.
00021  *
00022  * Except as contained in this notice, the name of Maxim Integrated
00023  * Products, Inc. shall not be used except as stated in the Maxim Integrated
00024  * Products, Inc. Branding Policy.
00025  *
00026  * The mere transfer of this software does not imply any licenses
00027  * of trade secrets, proprietary technology, copyrights, patents,
00028  * trademarks, maskwork rights, or any other form of intellectual
00029  * property whatsoever. Maxim Integrated Products, Inc. retains all
00030  * ownership rights.
00031  *******************************************************************************
00032  */
00033 
00034 #include "DSInterface.h"
00035 #include "SSBootloaderComm.h"
00036 #include "SSInterface.h"
00037 #include "Peripherals.h"
00038 #include "assert.h"
00039 #include "utils.h"
00040 
00041 static const char* const cmd_tbl[] = {
00042     "bootldr",
00043     "exit",
00044     "reset",
00045     "page_size",
00046     "num_pages",
00047     "set_iv",
00048     "set_auth",
00049     "erase",
00050     "page_erase",
00051     "flash",
00052     "set_cfg bl enter_mode",
00053     "set_cfg bl enter_pin",
00054     "set_cfg bl enter_pol",
00055     "set_cfg bl exit_mode",
00056     "set_cfg bl exit_to",
00057     "set_cfg bl save",
00058 };
00059 
00060 SSBootloaderComm::SSBootloaderComm(USBSerial *USB, SSInterface* ssInterface, DSInterface* dsInterface)
00061     :SensorComm("bl", false), m_USB(USB), ss_int(ssInterface), ds_int(dsInterface)
00062 {
00063 }
00064 
00065 int SSBootloaderComm::parse_auth(const char* cmd, uint8_t *auth_bytes)
00066 {
00067     char cmdStr[] = "set_auth ";
00068     int length = strlen(cmd);
00069     int expected_length = strlen(cmdStr) + 2*AES_AUTH_SIZE;
00070     if (length != expected_length) {
00071         pr_err("Couldn't parse Auth bytes, incorrect number of characters (len:%d, expected:%d)\n",
00072             length, expected_length);
00073         return COMM_INVALID_PARAM;
00074     }
00075 
00076     const char* macPtr = cmd + strlen(cmdStr);
00077 
00078     int num_found;
00079     int byteVal;
00080     for (int aidx = 0; aidx < AES_AUTH_SIZE; aidx++) {
00081         num_found = sscanf(macPtr, "%2X", &byteVal);
00082 
00083         if (num_found != 1 || byteVal > 0xFF) {
00084             pr_err("Couldn't parse byte %d of Auth\n", aidx);
00085             return COMM_INVALID_PARAM;
00086         }
00087 
00088         auth_bytes[aidx] = (uint8_t)byteVal;
00089         macPtr += 2;
00090     }
00091 
00092     return COMM_SUCCESS;
00093 }
00094 
00095 int SSBootloaderComm::parse_iv(const char* cmd, uint8_t* iv_bytes)
00096 {
00097     char cmdStr[] = "set_iv ";
00098     int length = strlen(cmd);
00099     int expected_length = strlen(cmdStr) + 2*AES_NONCE_SIZE;
00100     if (length != expected_length) {
00101         pr_err("Couldn't parse IV, incorrect number of characters (len:%d, expected:%d)\n",
00102                length, expected_length);
00103         return COMM_INVALID_PARAM;
00104     }
00105 
00106     const char* ivPtr = cmd + strlen(cmdStr);
00107 
00108     int num_found;
00109     int byteVal;
00110     for (int ividx = 0; ividx < AES_NONCE_SIZE; ividx++) {
00111         num_found = sscanf(ivPtr, "%2X", &byteVal);
00112 
00113         if (num_found != 1 || byteVal > 0xFF) {
00114             pr_err("Couldn't parse byte %d of IV\n", ividx);
00115             return COMM_INVALID_PARAM;
00116         }
00117         iv_bytes[ividx] = (uint8_t)byteVal;
00118         ivPtr += 2;
00119     }
00120 
00121     return COMM_SUCCESS;
00122 }
00123 
00124 bool SSBootloaderComm::parse_command(const char* cmd)
00125 {
00126     int ret = EXIT_SUCCESS;
00127     bool recognizedCmd = false;
00128 
00129     if (!ss_int) {
00130         pr_err("No SmartSensor Interface defined!");
00131         return false;
00132     }
00133     if (!ds_int) {
00134         pr_err("No DeviceStudio Interface defined!");
00135         return false;
00136     }
00137 
00138     for (int i = 0; i < NUM_CMDS; i++) {
00139         if (starts_with(cmd, cmd_tbl[i])) {
00140             cmd_state_t user_cmd = (cmd_state_t)i;
00141             recognizedCmd = true;
00142 
00143             switch (user_cmd) {
00144                 case cmd_enter_bootldr:
00145                 {
00146                     SS_STATUS status;
00147                     status = ss_int->reset_to_bootloader();
00148                     if (status == SS_SUCCESS)
00149                         m_USB->printf("\r\n%s err=%d\r\n", cmd, COMM_SUCCESS);
00150                     else
00151                         m_USB->printf("\r\n%s err=%d\r\n", cmd, COMM_GENERAL_ERROR);
00152 
00153                     uint8_t cmd_bytes[] = { SS_FAM_W_BOOTLOADER, SS_CMDIDX_STAY_IN_BTLRD };
00154                     status = ss_int->write_cmd(
00155                             &cmd_bytes[0], ARRAY_SIZE(cmd_bytes),
00156                             0, 0);
00157                     if (status == SS_SUCCESS)
00158                         m_USB->printf("\r\n%s err=%d\r\n", cmd, COMM_SUCCESS);
00159                     else
00160                         m_USB->printf("\r\n%s err=%d\r\n", cmd, COMM_GENERAL_ERROR);
00161 
00162 
00163                     ds_int->set_fw_platform(ss_int->get_ss_platform_name());
00164                     ds_int->set_fw_version(ss_int->get_ss_fw_version());
00165 
00166                     got_page_size = false;
00167                     sent_num_pages = false;
00168                 } break;
00169 
00170                 case cmd_exit_bootldr:
00171                 {
00172                     SS_STATUS status = ss_int->reset_to_main_app();
00173                     if (status == SS_SUCCESS)
00174                         m_USB->printf("\r\n%s err=%d\r\n", cmd, COMM_SUCCESS);
00175                     else
00176                         m_USB->printf("\r\n%s err=%d\r\n", cmd, COMM_GENERAL_ERROR);
00177 
00178                     ds_int->set_fw_platform(ss_int->get_ss_platform_name());
00179                     ds_int->set_fw_version(ss_int->get_ss_fw_version());
00180 
00181                 } break;
00182 
00183                 case cmd_reset:
00184                 {
00185                     SS_STATUS status = ss_int->reset();
00186                     if (status == SS_SUCCESS)
00187                         m_USB->printf("\r\n%s err=%d\r\n", cmd, COMM_SUCCESS);
00188                     else
00189                         m_USB->printf("\r\n%s err=%d\r\n", cmd, COMM_GENERAL_ERROR);
00190                     m_USB->printf("\r\n%s err=%d\r\n", cmd, ret);
00191 
00192                     ds_int->set_fw_platform(ss_int->get_ss_platform_name());
00193                     ds_int->set_fw_version(ss_int->get_ss_fw_version());
00194 
00195                 } break;
00196 
00197                 case cmd_page_size:
00198                 {
00199                     uint8_t cmd_bytes[] = { SS_FAM_R_BOOTLOADER, SS_CMDIDX_PAGESIZE };
00200                     uint8_t rxbuf[3];
00201 
00202                     SS_STATUS status = ss_int->read_cmd(
00203                             &cmd_bytes[0], ARRAY_SIZE(cmd_bytes),
00204                             0, 0,
00205                             &rxbuf[0], ARRAY_SIZE(rxbuf));
00206 
00207                     if (status == SS_SUCCESS) {
00208                         //rxbuf holds page size in big-endian format
00209                         page_size = (256*(int)rxbuf[1]) + rxbuf[2];
00210                         assert_msg(page_size <= MAX_PAGE_SIZE, "Page size exceeds maximum allowed");
00211 
00212                         m_USB->printf("\r\n%s value=%d err=%d\r\n", cmd, page_size, COMM_SUCCESS);
00213                         got_page_size = true;
00214 
00215                     } else {
00216                         m_USB->printf("\r\n%s err=%d\r\n", cmd, COMM_GENERAL_ERROR);
00217                     }
00218                 } break;
00219 
00220                 case cmd_num_pages:
00221                 {
00222                     int num_tok = sscanf(cmd, "num_pages %d", &num_pages);
00223                     if (num_tok != 1) {
00224                         m_USB->printf("\r\n%s value=%d err=%d\r\n", cmd, 0, COMM_INVALID_PARAM);
00225                         break;
00226                     }
00227 
00228                     uint8_t cmd_bytes[] = { SS_FAM_W_BOOTLOADER, SS_CMDIDX_SETNUMPAGES };
00229                     //num pages = 256*MSB + LSB
00230                     uint8_t data[] = { (uint8_t)((num_pages >> 8) & 0xFF), (uint8_t)(num_pages & 0xFF) };
00231 
00232                     SS_STATUS status = ss_int->write_cmd(
00233                             &cmd_bytes[0], ARRAY_SIZE(cmd_bytes),
00234                             &data[0], ARRAY_SIZE(data));
00235 
00236                     if (status == SS_SUCCESS) {
00237                         m_USB->printf("\r\n%s err=%d\r\n", cmd, COMM_SUCCESS);
00238                         sent_num_pages = true;
00239 
00240                     } else {
00241                         m_USB->printf("\r\n%s err=%d\r\n", cmd, COMM_GENERAL_ERROR);
00242                     }
00243                 } break;
00244 
00245                 case cmd_set_iv:
00246                 {
00247                     uint8_t iv_bytes[AES_NONCE_SIZE];
00248                     ret = parse_iv(cmd, &iv_bytes[0]);
00249                     if (ret != COMM_SUCCESS) {
00250                         m_USB->printf("\r\n%s err=%d\r\n", cmd, ret);
00251                     }
00252                     else
00253                     {
00254                         uint8_t cmd_bytes[] = { SS_FAM_W_BOOTLOADER, SS_CMDIDX_SETIV };
00255 
00256                         SS_STATUS status = ss_int->write_cmd(
00257                             &cmd_bytes[0], ARRAY_SIZE(cmd_bytes),
00258                             &iv_bytes[0], ARRAY_SIZE(iv_bytes));
00259 
00260                         if (status == SS_SUCCESS) {
00261                             m_USB->printf("\r\n%s err=%d\r\n", cmd, COMM_SUCCESS);
00262 
00263                         } else {
00264                             m_USB->printf("\r\n%s err=%d\r\n", cmd, COMM_GENERAL_ERROR);
00265                         }
00266                     }
00267                 } break;
00268 
00269                 case cmd_set_auth:
00270                 {
00271                     uint8_t auth_bytes[AES_AUTH_SIZE];
00272                     ret = parse_auth(cmd, &auth_bytes[0]);
00273                     if (ret != COMM_SUCCESS) {
00274                         m_USB->printf("\r\n%s err=%d\r\n", cmd, ret);
00275                     }
00276                     else
00277                     {
00278                         uint8_t cmd_bytes[] = { SS_FAM_W_BOOTLOADER, SS_CMDIDX_SETAUTH };
00279 
00280                         SS_STATUS status = ss_int->write_cmd(
00281                             &cmd_bytes[0], ARRAY_SIZE(cmd_bytes),
00282                             &auth_bytes[0], ARRAY_SIZE(auth_bytes));
00283 
00284                         if (status == SS_SUCCESS) {
00285                             m_USB->printf("\r\n%s err=%d\r\n", cmd, COMM_SUCCESS);
00286 
00287                         } else {
00288                             m_USB->printf("\r\n%s err=%d\r\n", cmd, COMM_GENERAL_ERROR);
00289                         }
00290                     }
00291                 } break;
00292 
00293                 case cmd_erase:
00294                 {
00295                     uint8_t cmd_bytes[] = { SS_FAM_W_BOOTLOADER, SS_CMDIDX_ERASE };
00296 
00297                     SS_STATUS status = ss_int->write_cmd(
00298                             &cmd_bytes[0], ARRAY_SIZE(cmd_bytes),
00299                             0, 0,
00300                             SS_BOOTLOADER_ERASE_DELAY);
00301                     if (status == SS_SUCCESS)
00302                         m_USB->printf("\r\n%s err=%d\r\n", cmd, COMM_SUCCESS);
00303                     else
00304                         m_USB->printf("\r\n%s err=%d\r\n", cmd, COMM_GENERAL_ERROR);
00305                 } break;
00306 
00307                 case cmd_page_erase:
00308                 {
00309                     int page_num_to_erase;
00310                     int num_tok = sscanf(cmd, "page_erase %d", &page_num_to_erase);
00311                     if (num_tok != 1) {
00312                         m_USB->printf("\r\n%s value=%d err=%d\r\n", cmd, 0, COMM_INVALID_PARAM);
00313                         break;
00314                     }
00315 
00316                     uint8_t cmd_bytes[] = { SS_FAM_W_BOOTLOADER, SS_CMDIDX_ERASE_PAGE };
00317                     //num pages = 256*MSB + LSB
00318                     uint8_t data[] = { (uint8_t)((page_num_to_erase >> 8) & 0xFF), (uint8_t)(page_num_to_erase & 0xFF) };
00319 
00320                     SS_STATUS status = ss_int->write_cmd(
00321                             &cmd_bytes[0], ARRAY_SIZE(cmd_bytes),
00322                             &data[0], ARRAY_SIZE(data), 50);
00323 
00324                     if (status == SS_SUCCESS) {
00325                         m_USB->printf("\r\n%s err=%d\r\n", cmd, COMM_SUCCESS);
00326                         sent_num_pages = true;
00327                     } else {
00328                         m_USB->printf("\r\n%s err=%d\r\n", cmd, COMM_GENERAL_ERROR);
00329                     }
00330                 } break;
00331 
00332                 case cmd_flash:
00333                 {
00334                     if (got_page_size && sent_num_pages) {
00335                         m_USB->printf("\r\n%s err=%d\r\n", cmd, COMM_SUCCESS);
00336                         flash_page_data();
00337                     } else {
00338                         pr_err("Can't enter flash mode. Need number of pages, and size of page"
00339                                 "(num_pages, page_size, commands)\r\n");
00340                         m_USB->printf("\r\n%s err=%d\r\n", cmd, COMM_GENERAL_ERROR);
00341                     }
00342                 } break;
00343 
00344                 case cmd_setcfg_bl_enter_mode:
00345                 {
00346                     uint8_t mode;
00347                     ret = parse_cmd_data(cmd, cmd_tbl[i], &mode, 1, false);
00348                     if (ret != 1) {
00349                         pr_err("parse_cmd_data=%d\r\n", ret);
00350                         m_USB->printf("\r\n%s err=%d\r\n", cmd, COMM_INVALID_PARAM);
00351                         break;
00352                     }
00353 
00354                     uint8_t cmd_bytes[] = { SS_FAM_W_BOOTLOADER_CFG, SS_CMDIDX_BL_ENTRY, SS_BL_CFG_ENTER_BL_MODE, mode };
00355                     SS_STATUS status = ss_int->write_cmd(
00356                             &cmd_bytes[0], ARRAY_SIZE(cmd_bytes),
00357                             0, 0);
00358                     if (status == SS_SUCCESS)
00359                         m_USB->printf("\r\n%s err=%d\r\n", cmd, COMM_SUCCESS);
00360                     else
00361                         m_USB->printf("\r\n%s err=%d\r\n", cmd, COMM_GENERAL_ERROR);
00362 
00363                 } break;
00364 
00365                 case cmd_setcfg_bl_ebl_pin:
00366                 {
00367                     uint8_t pin[2];
00368                     ret = parse_cmd_data(cmd, cmd_tbl[i], &pin[0], 2, false);
00369                     if (ret != 2) {
00370                         m_USB->printf("\r\n%s err=%d\r\n", cmd, COMM_INVALID_PARAM);
00371                         break;
00372                     }
00373 
00374                     uint8_t cmd_bytes[] = { SS_FAM_W_BOOTLOADER_CFG, SS_CMDIDX_BL_ENTRY, SS_BL_CFG_EBL_PIN,
00375                                             pin[0], pin[1]};
00376                     SS_STATUS status = ss_int->write_cmd(
00377                             &cmd_bytes[0], ARRAY_SIZE(cmd_bytes),
00378                             0, 0);
00379                     if (status == SS_SUCCESS)
00380                         m_USB->printf("\r\n%s err=%d\r\n", cmd, COMM_SUCCESS);
00381                     else
00382                         m_USB->printf("\r\n%s err=%d\r\n", cmd, COMM_GENERAL_ERROR);
00383 
00384                 } break;
00385 
00386                 case cmd_setcfg_bl_ebl_pol:
00387                 {
00388                     uint8_t mode;
00389                     ret = parse_cmd_data(cmd, cmd_tbl[i], &mode, 1, false);
00390                     if (ret != 1) {
00391                         m_USB->printf("\r\n%s err=%d\r\n", cmd, COMM_INVALID_PARAM);
00392                         break;
00393                     }
00394 
00395                     uint8_t cmd_bytes[] = { SS_FAM_W_BOOTLOADER_CFG, SS_CMDIDX_BL_ENTRY, SS_BL_CFG_EBL_POL, mode };
00396                     SS_STATUS status = ss_int->write_cmd(
00397                             &cmd_bytes[0], ARRAY_SIZE(cmd_bytes),
00398                             0, 0);
00399                     if (status == SS_SUCCESS)
00400                         m_USB->printf("\r\n%s err=%d\r\n", cmd, COMM_SUCCESS);
00401                     else
00402                         m_USB->printf("\r\n%s err=%d\r\n", cmd, COMM_GENERAL_ERROR);
00403 
00404                 } break;
00405 
00406                 case cmd_setcfg_bl_exit_mode:
00407                 {
00408                     uint8_t mode;
00409                     ret = parse_cmd_data(cmd, cmd_tbl[i], &mode, 1, false);
00410                     if (ret != 1) {
00411                         m_USB->printf("\r\n%s err=%d\r\n", cmd, COMM_INVALID_PARAM);
00412                         break;
00413                     }
00414 
00415                     uint8_t cmd_bytes[] = { SS_FAM_W_BOOTLOADER_CFG, SS_CMDIDX_BL_EXIT, SS_BL_CFG_EXIT_BL_MODE, mode };
00416                     SS_STATUS status = ss_int->write_cmd(
00417                             &cmd_bytes[0], ARRAY_SIZE(cmd_bytes),
00418                             0, 0);
00419                     if (status == SS_SUCCESS)
00420                         m_USB->printf("\r\n%s err=%d\r\n", cmd, COMM_SUCCESS);
00421                     else
00422                         m_USB->printf("\r\n%s err=%d\r\n", cmd, COMM_GENERAL_ERROR);
00423 
00424                 } break;
00425                 case cmd_setcfg_bl_timeout:
00426                 {
00427                     uint8_t to;
00428                     ret = parse_cmd_data(cmd, cmd_tbl[i], &to, 1, false);
00429                     if (ret != 1) {
00430                         m_USB->printf("\r\n%s err=%d\r\n", cmd, COMM_INVALID_PARAM);
00431                         break;
00432                     }
00433 
00434                     uint8_t cmd_bytes[] = { SS_FAM_W_BOOTLOADER_CFG, SS_CMDIDX_BL_EXIT, SS_BL_CFG_TIMEOUT, to };
00435                     SS_STATUS status = ss_int->write_cmd(
00436                             &cmd_bytes[0], ARRAY_SIZE(cmd_bytes),
00437                             0, 0);
00438                     if (status == SS_SUCCESS)
00439                         m_USB->printf("\r\n%s err=%d\r\n", cmd, COMM_SUCCESS);
00440                     else
00441                         m_USB->printf("\r\n%s err=%d\r\n", cmd, COMM_GENERAL_ERROR);
00442 
00443                 } break;
00444                 case cmd_setcfg_bl_save:
00445                 {
00446                     uint8_t cmd_bytes[] = { SS_FAM_W_BOOTLOADER_CFG, SS_CMDIDX_BL_SAVE };
00447 
00448                     SS_STATUS status = ss_int->write_cmd(
00449                             &cmd_bytes[0], ARRAY_SIZE(cmd_bytes),
00450                             0, 0, 50);
00451                     if (status == SS_SUCCESS)
00452                         m_USB->printf("\r\n%s err=%d\r\n", cmd, COMM_SUCCESS);
00453                     else
00454                         m_USB->printf("\r\n%s err=%d\r\n", cmd, COMM_GENERAL_ERROR);
00455 
00456                 } break;
00457 
00458                 default:
00459                 {
00460                     assert_msg(false, "Invalid switch case!");
00461                 }
00462             }
00463         }
00464     }
00465 
00466     return recognizedCmd;
00467 }
00468 
00469 void SSBootloaderComm::flash_page_data(void)
00470 {
00471     int totalBytes = 0;
00472     int currentPage = 1;
00473 
00474     static uint8_t tx_buf[MAX_PAGE_SIZE + CHECKBYTES_SIZE + 2] = { SS_FAM_W_BOOTLOADER, SS_CMDIDX_SENDPAGE };
00475     uint8_t *data_buffer = &tx_buf[2];
00476 
00477     while (currentPage <= num_pages) {
00478         pr_info("Waiting for page %d/%d data (%d bytes)...", currentPage, num_pages, page_size);
00479 
00480         //Collect page data + checksum from PC/Android
00481 //      totalBytes = 100;
00482         while (totalBytes < (page_size + CHECKBYTES_SIZE)) {
00483             data_buffer[totalBytes++] = m_USB->_getc();
00484         }
00485 
00486         pr_info("Done\r\n");
00487 
00488         //Send data to SmartSensor
00489         SS_STATUS status = ss_int->write_cmd(tx_buf, page_size + CHECKBYTES_SIZE + 2, 2000);
00490         pr_err("status: %d\r\n", status);
00491 
00492         //Inform PC/Andoid of status
00493         if (status == SS_ERR_BTLDR_CHECKSUM) {
00494             pr_err("Verify checksum failed!\r\n");
00495             m_USB->printf("\r\npageFlashDone err=%d\r\n", FLASH_ERR_CHECKSUM);
00496         } else if (status != SS_SUCCESS) {
00497             pr_err("Page flash failed!\r\n");
00498             m_USB->printf("\r\npageFlashDone err=%d\r\n", FLASH_ERR_GENERAL);
00499         } else {
00500             currentPage++;
00501             pr_err("Page flash successful!\r\n");
00502             m_USB->printf("\r\npageFlashDone err=%d\r\n", COMM_SUCCESS);
00503         }
00504 
00505         totalBytes = 0;
00506     }
00507 }