30#define SWITCHTEC_LIB_CORE
32#include "switchtec_priv.h"
34#include "switchtec/errors.h"
35#include "switchtec/endian.h"
36#include "switchtec/utils.h"
37#include "switchtec/mfg.h"
66enum switchtec_fw_part_type_gen4 {
67 SWITCHTEC_FW_IMG_TYPE_MAP_GEN4 = 0x0,
68 SWITCHTEC_FW_IMG_TYPE_KEYMAN_GEN4 = 0x1,
69 SWITCHTEC_FW_IMG_TYPE_BL2_GEN4 = 0x2,
70 SWITCHTEC_FW_IMG_TYPE_CFG_GEN4 = 0x3,
71 SWITCHTEC_FW_IMG_TYPE_IMG_GEN4 = 0x4,
72 SWITCHTEC_FW_IMG_TYPE_NVLOG_GEN4 = 0x5,
73 SWITCHTEC_FW_IMG_TYPE_SEEPROM_GEN4 = 0xFE,
74 SWITCHTEC_FW_IMG_TYPE_UNKNOWN_GEN4,
77enum switchtec_fw_part_type_gen5 {
78 SWITCHTEC_FW_IMG_TYPE_MAP_GEN5 = 0x0,
79 SWITCHTEC_FW_IMG_TYPE_KEYMAN_GEN5 = 0x1,
80 SWITCHTEC_FW_IMG_TYPE_RIOT_GEN5 = 0x2,
81 SWITCHTEC_FW_IMG_TYPE_BL2_GEN5 = 0x3,
82 SWITCHTEC_FW_IMG_TYPE_CFG_GEN5 = 0x4,
83 SWITCHTEC_FW_IMG_TYPE_IMG_GEN5 = 0x5,
84 SWITCHTEC_FW_IMG_TYPE_NVLOG_GEN5 = 0x6,
85 SWITCHTEC_FW_IMG_TYPE_SEEPROM_GEN5 = 0xFE,
86 SWITCHTEC_FW_IMG_TYPE_UNKNOWN_GEN5,
93 uint32_t secure_version;
95 uint32_t metadata_len;
108 uint8_t public_key_modulus[512];
109 uint8_t public_key_exponent[4];
113 uint8_t bist_gpio_pin_cfg;
114 uint8_t bist_gpio_level_cfg;
116 uint32_t xml_version;
117 uint32_t relocatable_img_len;
125 uint32_t hdr_version;
126 uint32_t secure_version;
128 uint32_t metadata_len;
141 uint8_t public_key_modulus[512];
142 uint8_t public_key_exponent[4];
146 uint8_t bist_gpio_pin_cfg;
147 uint8_t bist_gpio_level_cfg;
148 uint8_t rollback_enable;
150 uint32_t xml_version;
151 uint32_t relocatable_img_len;
159 uint32_t hdr_version;
160 uint32_t secure_version;
162 uint32_t metadata_len;
175 uint8_t public_key_modulus[512];
176 uint8_t public_key_exponent[4];
180 uint8_t bist_gpio_pin_cfg;
181 uint8_t bist_gpio_level_cfg;
182 uint8_t rollback_enable;
184 uint32_t xml_version;
185 uint32_t relocatable_img_len;
202 MRPC_FW_IMG_GET_CMD_START = 0,
203 MRPC_FW_IMG_GET_CMD_NEXT = 1,
205 MRPC_FW_IMG_GET_CMD_MAX
206} mrpc_fw_img_get_cmd_e;
212 uint8_t f_from_start;
215static uint32_t get_fw_tx_id(
struct switchtec_dev *dev)
218 return MRPC_FW_TX_GEN6;
220 return MRPC_FW_TX_GEN5;
227 enum mrpc_bg_status *bgstatus)
229 uint32_t cmd = MRPC_FWDNLD;
230 uint32_t subcmd = MRPC_FWDNLD_GET_STATUS;
239 cmd = get_fw_tx_id(dev);
242 &result,
sizeof(result));
248 *status = result.dlstatus;
250 if (bgstatus != NULL)
251 *bgstatus = result.bgstatus;
256static int switchtec_fw_wait(
struct switchtec_dev *dev,
259 enum mrpc_bg_status bgstatus;
270 if (bgstatus == MRPC_BG_STAT_OFFSET)
271 return SWITCHTEC_DLSTAT_ERROR_OFFSET;
273 if (bgstatus == MRPC_BG_STAT_ERROR) {
274 if (*status != SWITCHTEC_DLSTAT_INPROGRESS &&
275 *status != SWITCHTEC_DLSTAT_COMPLETES &&
276 *status != SWITCHTEC_DLSTAT_SUCCESS_FIRM_ACT &&
277 *status != SWITCHTEC_DLSTAT_SUCCESS_DATA_ACT)
280 return SWITCHTEC_DLSTAT_ERROR_PROGRAM;
283 }
while (bgstatus == MRPC_BG_STAT_INPROGRESS);
288static int set_redundant(
struct switchtec_dev *dev,
int type,
int set)
291 char *part_types[] = {
302 uint8_t redundant_val;
306 cmd.subcmd = MRPC_FWDNLD_SET_RDNDNT;
307 cmd.redundant_val = set;
309 cmd.part_type = type - 1;
311 cmd.part_type = type;
313 printf(
"%s redundant flag \t(%s)\n", set ?
"Checking" :
"Un-checking",
315 ret =
switchtec_cmd(dev, MRPC_FWDNLD, &cmd,
sizeof(cmd), NULL, 0);
317 fprintf(stderr,
"Error: setting redudant flag \t(%s)\n",
322 printf(
"Success: set redundant flag \t(%s)\n",
335 int riot,
int bl2,
int cfg,
int fw,
340 ret += set_redundant(dev, SWITCHTEC_PART_TYPE_KEYMAN, set);
342 ret += set_redundant(dev, SWITCHTEC_PART_TYPE_RC, set);
344 ret += set_redundant(dev, SWITCHTEC_PART_TYPE_BL2, set);
346 ret += set_redundant(dev, SWITCHTEC_PART_TYPE_CFG, set);
348 ret += set_redundant(dev, SWITCHTEC_PART_TYPE_FW, set);
369 void (*progress_callback)(
int cur,
int tot))
373 struct fw_img_get_resp_t {
384 uint8_t resp[MRPC_MAX_DATA_LEN] ={};
385 struct fw_img_get_resp_t *fw_img_get_resp = (
struct fw_img_get_resp_t *)resp;
389 if (ftruncate(fd, 0) == -1) {
395 cmd.fw_type = fw_type;
396 cmd.fw_slot = fw_slot;
397 cmd.f_from_start = MRPC_FW_IMG_GET_CMD_START;
403 printf(
"Error during FW image get\n");
407 size_t written = write(fd, (
void*)(&fw_img_get_resp->data), fw_img_get_resp->chunk_len);
408 if (written != fw_img_get_resp->chunk_len) {
409 perror(
"Error writing to file");
413 if (progress_callback)
414 progress_callback(fw_img_get_resp->offset, fw_img_get_resp->total_len);
418 cmd.fw_type = fw_type;
419 cmd.fw_slot = fw_slot;
420 cmd.f_from_start = MRPC_FW_IMG_GET_CMD_NEXT;
426 printf(
"Error during FW image get\n");
430 size_t written = write(fd, (
void *)(&fw_img_get_resp->data), fw_img_get_resp->chunk_len);
431 if (written != fw_img_get_resp->chunk_len) {
432 perror(
"Error writing to file");
436 if (progress_callback)
437 progress_callback(fw_img_get_resp->offset, fw_img_get_resp->total_len);
439 }
while ((fw_img_get_resp->offset + fw_img_get_resp->chunk_len) < fw_img_get_resp->total_len);
455 int toggle_bl2,
int toggle_key,
456 int toggle_fw,
int toggle_cfg,
468 uint8_t toggle_riotcore;
473 cmd_size =
sizeof(cmd);
474 cmd_id = get_fw_tx_id(dev);
475 cmd.subcmd = MRPC_FW_TX_TOGGLE;
476 cmd.toggle_bl2 = !!toggle_bl2;
481 cmd.toggle_fw = !!toggle_fw;
486 cmd.toggle_cfg = !!toggle_cfg;
494 cmd_id = MRPC_FWDNLD;
495 cmd.subcmd = MRPC_FWDNLD_TOGGLE;
496 cmd.toggle_bl2 = !!toggle_bl2;
497 cmd.toggle_key = !!toggle_key;
498 cmd.toggle_fw = !!toggle_fw;
499 cmd.toggle_cfg = !!toggle_cfg;
501 cmd.toggle_riotcore = !!toggle_riotcore;
502 cmd_size =
sizeof(cmd);
511 uint8_t dont_activate;
517 uint8_t data[MRPC_MAX_DATA_LEN -
sizeof(
struct cmd_fwdl_hdr)];
532 int dont_activate,
int force,
533 void (*progress_callback)(
int cur,
int tot))
536 enum mrpc_bg_status bgstatus;
537 ssize_t image_size, offset = 0;
540 uint32_t cmd_id = MRPC_FWDNLD;
543 cmd_id = get_fw_tx_id(dev);
545 image_size = lseek(img_fd, 0, SEEK_END);
548 lseek(img_fd, 0, SEEK_SET);
552 if (!force && status == SWITCHTEC_DLSTAT_INPROGRESS) {
557 if (bgstatus == MRPC_BG_STAT_INPROGRESS) {
563 cmd.hdr.subcmd = MRPC_FW_TX_FLASH;
565 cmd.hdr.subcmd = MRPC_FWDNLD_DOWNLOAD;
567 cmd.hdr.dont_activate = !!dont_activate;
568 cmd.hdr.img_length = htole32(image_size);
570 while (offset < image_size) {
571 ssize_t blklen = read(img_fd, &cmd.data,
574 if (blklen == -EAGAIN || blklen == -EWOULDBLOCK)
583 cmd.hdr.offset = htole32(offset);
584 cmd.hdr.blk_length = htole32(blklen);
592 ret = switchtec_fw_wait(dev, &status);
596 offset += le32toh(cmd.hdr.blk_length);
598 if (progress_callback)
599 progress_callback(offset, image_size);
603 if (status == SWITCHTEC_DLSTAT_COMPLETES)
606 if (status == SWITCHTEC_DLSTAT_SUCCESS_FIRM_ACT)
609 if (status == SWITCHTEC_DLSTAT_SUCCESS_DATA_ACT)
613 return SWITCHTEC_DLSTAT_HARDWARE_ERR;
625 uint8_t major = (version >> 24) & 0xff;
629 case 2:
return SWITCHTEC_GEN3;
632 case 5:
return SWITCHTEC_GEN4;
635 case 8:
return SWITCHTEC_GEN5;
638 case 11:
return SWITCHTEC_GEN6;
639 default:
return SWITCHTEC_GEN_UNKNOWN;
655 int dont_activate,
int force,
656 void (*progress_callback)(
int cur,
int tot))
659 enum mrpc_bg_status bgstatus;
660 ssize_t image_size, offset = 0;
663 uint32_t cmd_id = MRPC_FWDNLD;
666 cmd_id = get_fw_tx_id(dev);
668 ret = fseek(fimg, 0, SEEK_END);
671 image_size = ftell(fimg);
674 ret = fseek(fimg, 0, SEEK_SET);
680 if (!force && status == SWITCHTEC_DLSTAT_INPROGRESS) {
685 if (bgstatus == MRPC_BG_STAT_INPROGRESS) {
691 cmd.hdr.subcmd = MRPC_FW_TX_FLASH;
693 cmd.hdr.subcmd = MRPC_FWDNLD_DOWNLOAD;
695 cmd.hdr.dont_activate = !!dont_activate;
696 cmd.hdr.img_length = htole32(image_size);
698 while (offset < image_size) {
699 ssize_t blklen = fread(&cmd.data, 1,
sizeof(cmd.data), fimg);
708 cmd.hdr.offset = htole32(offset);
709 cmd.hdr.blk_length = htole32(blklen);
717 ret = switchtec_fw_wait(dev, &status);
721 offset += le32toh(cmd.hdr.blk_length);
723 if (progress_callback)
724 progress_callback(offset, image_size);
727 if (status == SWITCHTEC_DLSTAT_COMPLETES)
730 if (status == SWITCHTEC_DLSTAT_SUCCESS_FIRM_ACT)
733 if (status == SWITCHTEC_DLSTAT_SUCCESS_DATA_ACT)
737 return SWITCHTEC_DLSTAT_HARDWARE_ERR;
760 case SWITCHTEC_DLSTAT_HEADER_INCORRECT:
761 msg =
"Header incorrect";
break;
762 case SWITCHTEC_DLSTAT_OFFSET_INCORRECT:
763 msg =
"Offset incorrect";
break;
764 case SWITCHTEC_DLSTAT_CRC_INCORRECT:
765 msg =
"CRC incorrect";
break;
766 case SWITCHTEC_DLSTAT_LENGTH_INCORRECT:
767 msg =
"Length incorrect";
break;
768 case SWITCHTEC_DLSTAT_HARDWARE_ERR:
769 msg =
"Hardware Error";
break;
770 case SWITCHTEC_DLSTAT_PACKAGE_TOO_SMALL:
771 msg =
"Package length less than 32 bytes";
break;
772 case SWITCHTEC_DLSTAT_SIG_MEM_ALLOC:
773 msg =
"Signature memory allocation failed";
break;
774 case SWITCHTEC_DLSTAT_SEEPROM:
775 msg =
"SEEPROM download failed";
break;
776 case SWITCHTEC_DLSTAT_READONLY_PARTITION:
777 msg =
"Programming a read-only partition";
break;
778 case SWITCHTEC_DLSTAT_DOWNLOAD_TIMEOUT:
779 msg =
"Download Timeout";
break;
780 case SWITCHTEC_DLSTAT_SEEPROM_TWI_NOT_ENABLED:
781 msg =
"SEEPROM or related TWI bus isn't enabled";
break;
782 case SWITCHTEC_DLSTAT_PROGRAM_RUNNING:
783 msg =
"Programming a running partition";
break;
784 case SWITCHTEC_DLSTAT_NOT_ALLOWED:
785 msg =
"Programming not allowed over this interface";
break;
786 case SWITCHTEC_DLSTAT_XML_MISMATCH_ACT:
787 msg =
"Activation failed due to XML version mismatch";
break;
788 case SWITCHTEC_DLSTAT_UNKNOWN_ACT:
789 msg =
"Activation failed due to unknown error";
break;
790 case SWITCHTEC_DLSTAT_ERROR_OFFSET:
791 msg =
"Data offset error during programming";
break;
792 case SWITCHTEC_DLSTAT_ERROR_PROGRAM:
793 msg =
"Failed to program to flash";
break;
795 case SWITCHTEC_DLSTAT_NO_FILE:
796 msg =
"No Image Transferred";
break;
798 fprintf(stderr,
"%s: Unknown Error (0x%x)\n", s, ret);
802 fprintf(stderr,
"%s: %s\n", s, msg);
805static enum switchtec_fw_type
808 switch ((
unsigned long)info->
part_id) {
809 case SWITCHTEC_FW_PART_ID_G3_BOOT:
return SWITCHTEC_FW_TYPE_BOOT;
810 case SWITCHTEC_FW_PART_ID_G3_MAP0:
return SWITCHTEC_FW_TYPE_MAP;
811 case SWITCHTEC_FW_PART_ID_G3_MAP1:
return SWITCHTEC_FW_TYPE_MAP;
812 case SWITCHTEC_FW_PART_ID_G3_IMG0:
return SWITCHTEC_FW_TYPE_IMG;
813 case SWITCHTEC_FW_PART_ID_G3_IMG1:
return SWITCHTEC_FW_TYPE_IMG;
814 case SWITCHTEC_FW_PART_ID_G3_DAT0:
return SWITCHTEC_FW_TYPE_CFG;
815 case SWITCHTEC_FW_PART_ID_G3_DAT1:
return SWITCHTEC_FW_TYPE_CFG;
816 case SWITCHTEC_FW_PART_ID_G3_NVLOG:
return SWITCHTEC_FW_TYPE_NVLOG;
817 case SWITCHTEC_FW_PART_ID_G3_SEEPROM:
return SWITCHTEC_FW_TYPE_SEEPROM;
820 case 0xa8000000:
return SWITCHTEC_FW_TYPE_BOOT;
821 case 0xa8020000:
return SWITCHTEC_FW_TYPE_MAP;
822 case 0xa8060000:
return SWITCHTEC_FW_TYPE_IMG;
823 case 0xa8210000:
return SWITCHTEC_FW_TYPE_CFG;
825 default:
return SWITCHTEC_FW_TYPE_UNKNOWN;
829static enum switchtec_fw_type
833 case SWITCHTEC_FW_PART_ID_G4_MAP0:
return SWITCHTEC_FW_TYPE_MAP;
834 case SWITCHTEC_FW_PART_ID_G4_MAP1:
return SWITCHTEC_FW_TYPE_MAP;
835 case SWITCHTEC_FW_PART_ID_G4_KEY0:
return SWITCHTEC_FW_TYPE_KEY;
836 case SWITCHTEC_FW_PART_ID_G4_KEY1:
return SWITCHTEC_FW_TYPE_KEY;
837 case SWITCHTEC_FW_PART_ID_G4_BL20:
return SWITCHTEC_FW_TYPE_BL2;
838 case SWITCHTEC_FW_PART_ID_G4_BL21:
return SWITCHTEC_FW_TYPE_BL2;
839 case SWITCHTEC_FW_PART_ID_G4_CFG0:
return SWITCHTEC_FW_TYPE_CFG;
840 case SWITCHTEC_FW_PART_ID_G4_CFG1:
return SWITCHTEC_FW_TYPE_CFG;
841 case SWITCHTEC_FW_PART_ID_G4_IMG0:
return SWITCHTEC_FW_TYPE_IMG;
842 case SWITCHTEC_FW_PART_ID_G4_IMG1:
return SWITCHTEC_FW_TYPE_IMG;
843 case SWITCHTEC_FW_PART_ID_G4_NVLOG:
return SWITCHTEC_FW_TYPE_NVLOG;
844 case SWITCHTEC_FW_PART_ID_G4_SEEPROM:
return SWITCHTEC_FW_TYPE_SEEPROM;
845 default:
return SWITCHTEC_FW_TYPE_UNKNOWN;
849static enum switchtec_fw_type
853 case SWITCHTEC_FW_PART_ID_G5_MAP0:
return SWITCHTEC_FW_TYPE_MAP;
854 case SWITCHTEC_FW_PART_ID_G5_MAP1:
return SWITCHTEC_FW_TYPE_MAP;
855 case SWITCHTEC_FW_PART_ID_G5_KEY0:
return SWITCHTEC_FW_TYPE_KEY;
856 case SWITCHTEC_FW_PART_ID_G5_KEY1:
return SWITCHTEC_FW_TYPE_KEY;
857 case SWITCHTEC_FW_PART_ID_G5_RIOT0:
return SWITCHTEC_FW_TYPE_RIOT;
858 case SWITCHTEC_FW_PART_ID_G5_RIOT1:
return SWITCHTEC_FW_TYPE_RIOT;
859 case SWITCHTEC_FW_PART_ID_G5_BL20:
return SWITCHTEC_FW_TYPE_BL2;
860 case SWITCHTEC_FW_PART_ID_G5_BL21:
return SWITCHTEC_FW_TYPE_BL2;
861 case SWITCHTEC_FW_PART_ID_G5_CFG0:
return SWITCHTEC_FW_TYPE_CFG;
862 case SWITCHTEC_FW_PART_ID_G5_CFG1:
return SWITCHTEC_FW_TYPE_CFG;
863 case SWITCHTEC_FW_PART_ID_G5_IMG0:
return SWITCHTEC_FW_TYPE_IMG;
864 case SWITCHTEC_FW_PART_ID_G5_IMG1:
return SWITCHTEC_FW_TYPE_IMG;
865 case SWITCHTEC_FW_PART_ID_G5_NVLOG:
return SWITCHTEC_FW_TYPE_NVLOG;
866 case SWITCHTEC_FW_PART_ID_G5_SEEPROM:
return SWITCHTEC_FW_TYPE_SEEPROM;
867 default:
return SWITCHTEC_FW_TYPE_UNKNOWN;
871static enum switchtec_fw_type
875 case SWITCHTEC_FW_PART_ID_G6_MAP0:
return SWITCHTEC_FW_TYPE_MAP;
876 case SWITCHTEC_FW_PART_ID_G6_MAP1:
return SWITCHTEC_FW_TYPE_MAP;
877 case SWITCHTEC_FW_PART_ID_G6_KEY0:
return SWITCHTEC_FW_TYPE_KEY;
878 case SWITCHTEC_FW_PART_ID_G6_KEY1:
return SWITCHTEC_FW_TYPE_KEY;
879 case SWITCHTEC_FW_PART_ID_G6_BL20:
return SWITCHTEC_FW_TYPE_BL2;
880 case SWITCHTEC_FW_PART_ID_G6_BL21:
return SWITCHTEC_FW_TYPE_BL2;
881 case SWITCHTEC_FW_PART_ID_G6_CFG0:
return SWITCHTEC_FW_TYPE_CFG;
882 case SWITCHTEC_FW_PART_ID_G6_CFG1:
return SWITCHTEC_FW_TYPE_CFG;
883 case SWITCHTEC_FW_PART_ID_G6_IMG0:
return SWITCHTEC_FW_TYPE_IMG;
884 case SWITCHTEC_FW_PART_ID_G6_IMG1:
return SWITCHTEC_FW_TYPE_IMG;
885 case SWITCHTEC_FW_PART_ID_G6_NVLOG:
return SWITCHTEC_FW_TYPE_NVLOG;
886 case SWITCHTEC_FW_PART_ID_G6_SEEPROM:
return SWITCHTEC_FW_TYPE_SEEPROM;
887 default:
return SWITCHTEC_FW_TYPE_UNKNOWN;
891static enum switchtec_fw_type
895 case SWITCHTEC_GEN3:
return switchtec_fw_id_to_type_gen3(info);
896 case SWITCHTEC_GEN4:
return switchtec_fw_id_to_type_gen4(info);
897 case SWITCHTEC_GEN5:
return switchtec_fw_id_to_type_gen5(info);
898 case SWITCHTEC_GEN6:
return switchtec_fw_id_to_type_gen6(info);
899 default:
return SWITCHTEC_FW_TYPE_UNKNOWN;
903static int switchtec_fw_file_info_gen3(
int fd,
909 ret = read(fd, &hdr,
sizeof(hdr));
910 lseek(fd, 0, SEEK_SET);
912 if (ret !=
sizeof(hdr))
915 if (strcmp(hdr.magic,
"PMC") != 0)
921 info->
gen = SWITCHTEC_GEN3;
923 info->
image_crc = le32toh(hdr.image_crc);
924 version_to_string(hdr.version, info->
version,
sizeof(info->
version));
925 info->
image_len = le32toh(hdr.image_len);
927 info->
type = switchtec_fw_id_to_type(info);
929 info->secure_version = 0;
930 info->signed_image = 0;
939static enum switchtec_fw_image_part_id_gen4 hdr_type2_id_gen4(uint32_t type)
942 case SWITCHTEC_FW_IMG_TYPE_MAP_GEN4:
943 return SWITCHTEC_FW_PART_ID_G4_MAP0;
945 case SWITCHTEC_FW_IMG_TYPE_KEYMAN_GEN4:
946 return SWITCHTEC_FW_PART_ID_G4_KEY0;
948 case SWITCHTEC_FW_IMG_TYPE_BL2_GEN4:
949 return SWITCHTEC_FW_PART_ID_G4_BL20;
951 case SWITCHTEC_FW_IMG_TYPE_CFG_GEN4:
952 return SWITCHTEC_FW_PART_ID_G4_CFG0;
954 case SWITCHTEC_FW_IMG_TYPE_IMG_GEN4:
955 return SWITCHTEC_FW_PART_ID_G4_IMG0;
957 case SWITCHTEC_FW_IMG_TYPE_NVLOG_GEN4:
958 return SWITCHTEC_FW_PART_ID_G4_NVLOG;
960 case SWITCHTEC_FW_IMG_TYPE_SEEPROM_GEN4:
961 return SWITCHTEC_FW_PART_ID_G4_SEEPROM;
968static enum switchtec_fw_image_part_id_gen5 hdr_type2_id_gen5(uint32_t type)
971 case SWITCHTEC_FW_IMG_TYPE_MAP_GEN5:
972 return SWITCHTEC_FW_PART_ID_G5_MAP0;
974 case SWITCHTEC_FW_IMG_TYPE_KEYMAN_GEN5:
975 return SWITCHTEC_FW_PART_ID_G5_KEY0;
977 case SWITCHTEC_FW_IMG_TYPE_RIOT_GEN5:
978 return SWITCHTEC_FW_PART_ID_G5_RIOT0;
980 case SWITCHTEC_FW_IMG_TYPE_BL2_GEN5:
981 return SWITCHTEC_FW_PART_ID_G5_BL20;
983 case SWITCHTEC_FW_IMG_TYPE_CFG_GEN5:
984 return SWITCHTEC_FW_PART_ID_G5_CFG0;
986 case SWITCHTEC_FW_IMG_TYPE_IMG_GEN5:
987 return SWITCHTEC_FW_PART_ID_G5_IMG0;
989 case SWITCHTEC_FW_IMG_TYPE_NVLOG_GEN5:
990 return SWITCHTEC_FW_PART_ID_G5_NVLOG;
992 case SWITCHTEC_FW_IMG_TYPE_SEEPROM_GEN5:
993 return SWITCHTEC_FW_PART_ID_G5_SEEPROM;
1000static int switchtec_fw_file_info_gen45(
int fd,
1005 uint8_t exp_zero[4] = {};
1009 ret = read(fd, &hdr,
sizeof(hdr));
1010 lseek(fd, 0, SEEK_SET);
1012 if (ret !=
sizeof(hdr))
1015 if (strncmp(hdr.magic,
"MSCC",
sizeof(hdr.magic)))
1018 if (strncmp(hdr.sub_magic,
"_MD ",
sizeof(hdr.sub_magic)))
1026 part_id = hdr_type2_id_gen5(le32toh(hdr.type));
1028 part_id = hdr_type2_id_gen4(le32toh(hdr.type));
1035 info->
image_crc = le32toh(hdr.image_crc);
1036 version = le32toh(hdr.version);
1037 version_to_string(version, info->
version,
sizeof(info->
version));
1038 info->
image_len = le32toh(hdr.image_len);
1041 info->
type = switchtec_fw_id_to_type(info);
1043 info->secure_version = le32toh(hdr.secure_version);
1044 info->signed_image = !!memcmp(hdr.public_key_exponent, exp_zero, 4);
1064 ret = read(fd, &magic,
sizeof(magic));
1065 lseek(fd, 0, SEEK_SET);
1067 if (ret !=
sizeof(magic)) {
1072 if (!strncmp(magic,
"PMC",
sizeof(magic))) {
1073 return switchtec_fw_file_info_gen3(fd, info);
1074 }
else if (!strncmp(magic,
"MSCC",
sizeof(magic))) {
1075 return switchtec_fw_file_info_gen45(fd, info);
1076 }
else if (!strncmp(magic,
"DCBI",
sizeof(magic))) {
1108 if (!info.signed_image)
1113 sn_info.ver_bl2 = 0xffffffff;
1114 sn_info.ver_main = 0xffffffff;
1115 sn_info.ver_km = 0xffffffff;
1118 switch (info.
type) {
1119 case SWITCHTEC_FW_TYPE_BL2:
1120 if (info.secure_version > sn_info.ver_bl2)
1124 case SWITCHTEC_FW_TYPE_IMG:
1125 if (info.secure_version > sn_info.ver_main)
1129 case SWITCHTEC_FW_TYPE_KEY:
1130 if (info.secure_version > sn_info.ver_km)
1148 switch (info->
type) {
1149 case SWITCHTEC_FW_TYPE_BOOT:
return "BOOT";
1150 case SWITCHTEC_FW_TYPE_MAP:
return "MAP";
1151 case SWITCHTEC_FW_TYPE_IMG:
return "IMG";
1152 case SWITCHTEC_FW_TYPE_CFG:
return "CFG";
1153 case SWITCHTEC_FW_TYPE_KEY:
return "KEY";
1154 case SWITCHTEC_FW_TYPE_RIOT:
return "RIOT";
1155 case SWITCHTEC_FW_TYPE_BL2:
return "BL2";
1156 case SWITCHTEC_FW_TYPE_NVLOG:
return "NVLOG";
1157 case SWITCHTEC_FW_TYPE_SEEPROM:
return "SEEPROM";
1158 default:
return "UNKNOWN";
1162static int switchtec_fw_map_get_active(
struct switchtec_dev *dev,
1165 uint32_t map0_update_index;
1166 uint32_t map1_update_index;
1170 sizeof(uint32_t), &map0_update_index);
1175 sizeof(uint32_t), &map1_update_index);
1180 if (map0_update_index > map1_update_index) {
1181 if (info->
part_addr == SWITCHTEC_FLASH_MAP0_PART_START)
1184 if (info->
part_addr == SWITCHTEC_FLASH_MAP1_PART_START)
1191static int switchtec_fw_info_metadata_gen3(
struct switchtec_dev *dev,
1198 if (inf->
part_id == SWITCHTEC_FW_PART_ID_G3_NVLOG)
1201 metadata = malloc(
sizeof(*metadata));
1211 if (strncmp(metadata->magic,
"PMC",
sizeof(metadata->magic)))
1214 version_to_string(metadata->version, inf->
version,
1219 inf->metadata = metadata;
1228static int switchtec_fw_part_info_gen3(
struct switchtec_dev *dev,
1236 case SWITCHTEC_FW_PART_ID_G3_BOOT:
1237 inf->
part_addr = SWITCHTEC_FLASH_BOOT_PART_START;
1238 inf->
part_len = SWITCHTEC_FLASH_PART_LEN;
1241 case SWITCHTEC_FW_PART_ID_G3_MAP0:
1242 inf->
part_addr = SWITCHTEC_FLASH_MAP0_PART_START;
1243 inf->
part_len = SWITCHTEC_FLASH_PART_LEN;
1244 ret = switchtec_fw_map_get_active(dev, inf);
1246 case SWITCHTEC_FW_PART_ID_G3_MAP1:
1247 inf->
part_addr = SWITCHTEC_FLASH_MAP1_PART_START;
1248 inf->
part_len = SWITCHTEC_FLASH_PART_LEN;
1249 ret = switchtec_fw_map_get_active(dev, inf);
1253 inf->read_only =
false;
1261 if (inf->
part_id == SWITCHTEC_FW_PART_ID_G3_NVLOG)
1264 return switchtec_fw_info_metadata_gen3(dev, inf);
1267static int switchtec_fw_info_metadata_gen4(
struct switchtec_dev *dev,
1275 .subcmd = MRPC_PART_INFO_GET_METADATA,
1280 if (inf->
part_id == SWITCHTEC_FW_PART_ID_G4_NVLOG)
1282 if (inf->
part_id == SWITCHTEC_FW_PART_ID_G4_SEEPROM)
1283 subcmd.subcmd = MRPC_PART_INFO_GET_SEEPROM;
1285 metadata = malloc(
sizeof(*metadata));
1289 ret =
switchtec_cmd(dev, MRPC_PART_INFO, &subcmd,
sizeof(subcmd),
1290 metadata,
sizeof(*metadata));
1294 if (strncmp(metadata->magic,
"MSCC",
sizeof(metadata->magic)))
1297 if (strncmp(metadata->sub_magic,
"_MD ",
sizeof(metadata->sub_magic)))
1300 version_to_string(le32toh(metadata->version), inf->
version,
1303 inf->
image_crc = le32toh(metadata->image_crc);
1304 inf->
image_len = le32toh(metadata->image_len);
1305 inf->metadata = metadata;
1314static int switchtec_fw_info_metadata_gen5(
struct switchtec_dev *dev,
1322 .subcmd = MRPC_PART_INFO_GET_METADATA_GEN5,
1327 if (inf->
part_id == SWITCHTEC_FW_PART_ID_G5_NVLOG)
1329 if (inf->
part_id == SWITCHTEC_FW_PART_ID_G5_SEEPROM)
1330 subcmd.subcmd = MRPC_PART_INFO_GET_SEEPROM;
1332 metadata = malloc(
sizeof(*metadata));
1336 ret =
switchtec_cmd(dev, MRPC_PART_INFO, &subcmd,
sizeof(subcmd),
1337 metadata,
sizeof(*metadata));
1341 if (strncmp(metadata->magic,
"MSCC",
sizeof(metadata->magic)))
1344 if (strncmp(metadata->sub_magic,
"_MD ",
sizeof(metadata->sub_magic)))
1347 version_to_string(le32toh(metadata->version), inf->
version,
1350 inf->
image_crc = le32toh(metadata->image_crc);
1351 inf->
image_len = le32toh(metadata->image_len);
1352 inf->metadata = metadata;
1361static int switchtec_fw_info_metadata_gen6(
struct switchtec_dev *dev,
1369 .subcmd = MRPC_PART_INFO_GET_METADATA_GEN6,
1374 if (inf->
part_id == SWITCHTEC_FW_PART_ID_G6_NVLOG)
1376 if (inf->
part_id == SWITCHTEC_FW_PART_ID_G6_SEEPROM)
1377 subcmd.subcmd = MRPC_PART_INFO_GET_SEEPROM_GEN6;
1379 metadata = malloc(
sizeof(*metadata));
1383 ret =
switchtec_cmd(dev, MRPC_PART_INFO, &subcmd,
sizeof(subcmd),
1384 metadata,
sizeof(*metadata));
1388 version_to_string(le32toh(metadata->version), inf->
version,
1391 inf->
image_crc = le32toh(metadata->image_crc);
1392 inf->
image_len = le32toh(metadata->image_len);
1393 inf->metadata = metadata;
1403 uint32_t firmware_version;
1404 uint32_t flash_size;
1408 uint8_t running_bl2_flag;
1409 uint8_t running_cfg_flag;
1410 uint8_t running_img_flag;
1411 uint8_t running_key_flag;
1416 uint16_t image_version;
1419 uint32_t part_start;
1421 uint32_t part_offset;
1422 uint32_t part_size_dw;
1426 } map0, map1, keyman0, keyman1, bl20, bl21, cfg0, cfg1,
1427 img0, img1, nvlog, vendor[8];
1431 uint32_t firmware_version;
1432 uint32_t flash_size;
1436 uint8_t running_riot_flag;
1437 uint8_t running_bl2_flag;
1438 uint8_t running_cfg_flag;
1439 uint8_t running_img_flag;
1440 uint8_t running_key_flag;
1442 uint8_t key_redundant_flag;
1443 uint8_t riot_redundant_flag;
1444 uint8_t bl2_redundant_flag;
1445 uint8_t cfg_redundant_flag;
1446 uint8_t img_redundant_flag;
1449 struct switchtec_flash_part_info_gen4 map0, map1, keyman0, keyman1,
1450 riot0, riot1, bl20, bl21,
1451 cfg0, cfg1, img0, img1, nvlog,
1456 uint32_t firmware_version;
1457 uint32_t flash_size;
1461 uint8_t running_bl2_flag;
1462 uint8_t running_cfg_flag;
1463 uint8_t running_img_flag;
1464 uint8_t running_key_flag;
1466 uint8_t key_redundant_flag;
1467 uint8_t bl2_redundant_flag;
1468 uint8_t cfg_redundant_flag;
1469 uint8_t img_redundant_flag;
1472 struct switchtec_flash_part_info_gen4 map0, map1, keyman0, keyman1, bl20,
1473 bl21, cfg0, cfg1, img0, img1,
1477static int switchtec_fw_part_info_gen4(
struct switchtec_dev *dev,
1481 struct switchtec_flash_part_info_gen4 *part_info;
1485 case SWITCHTEC_FW_PART_ID_G4_MAP0:
1486 part_info = &all->map0;
1488 case SWITCHTEC_FW_PART_ID_G4_MAP1:
1489 part_info = &all->map1;
1491 case SWITCHTEC_FW_PART_ID_G4_KEY0:
1492 part_info = &all->keyman0;
1494 case SWITCHTEC_FW_PART_ID_G4_KEY1:
1495 part_info = &all->keyman1;
1497 case SWITCHTEC_FW_PART_ID_G4_BL20:
1498 part_info = &all->bl20;
1500 case SWITCHTEC_FW_PART_ID_G4_BL21:
1501 part_info = &all->bl21;
1503 case SWITCHTEC_FW_PART_ID_G4_IMG0:
1504 part_info = &all->img0;
1506 case SWITCHTEC_FW_PART_ID_G4_IMG1:
1507 part_info = &all->img1;
1509 case SWITCHTEC_FW_PART_ID_G4_CFG0:
1510 part_info = &all->cfg0;
1512 case SWITCHTEC_FW_PART_ID_G4_CFG1:
1513 part_info = &all->cfg1;
1515 case SWITCHTEC_FW_PART_ID_G4_NVLOG:
1516 part_info = &all->nvlog;
1518 case SWITCHTEC_FW_PART_ID_G4_SEEPROM:
1526 ret = switchtec_fw_info_metadata_gen4(dev, inf);
1528 inf->running =
true;
1538 inf->
part_addr = le32toh(part_info->part_start);
1539 inf->
part_len = le32toh(part_info->part_size_dw) * 4;
1540 inf->active = part_info->active;
1541 inf->running = part_info->is_using;
1542 inf->read_only = part_info->read_only;
1543 inf->valid = part_info->valid;
1547 return switchtec_fw_info_metadata_gen4(dev, inf);
1550static int switchtec_fw_part_info_gen5(
struct switchtec_dev *dev,
1554 struct switchtec_flash_part_info_gen4 *part_info;
1558 case SWITCHTEC_FW_PART_ID_G5_MAP0:
1559 part_info = &all->map0;
1561 case SWITCHTEC_FW_PART_ID_G5_MAP1:
1562 part_info = &all->map1;
1564 case SWITCHTEC_FW_PART_ID_G5_RIOT0:
1565 inf->redundant = all->riot_redundant_flag;
1566 part_info = &all->riot0;
1568 case SWITCHTEC_FW_PART_ID_G5_RIOT1:
1569 inf->redundant = all->riot_redundant_flag;
1570 part_info = &all->riot1;
1572 case SWITCHTEC_FW_PART_ID_G5_KEY0:
1573 inf->redundant = all->key_redundant_flag;
1574 part_info = &all->keyman0;
1576 case SWITCHTEC_FW_PART_ID_G5_KEY1:
1577 inf->redundant = all->key_redundant_flag;
1578 part_info = &all->keyman1;
1580 case SWITCHTEC_FW_PART_ID_G5_BL20:
1581 inf->redundant = all->bl2_redundant_flag;
1582 part_info = &all->bl20;
1584 case SWITCHTEC_FW_PART_ID_G5_BL21:
1585 inf->redundant = all->bl2_redundant_flag;
1586 part_info = &all->bl21;
1588 case SWITCHTEC_FW_PART_ID_G5_IMG0:
1589 inf->redundant = all->img_redundant_flag;
1590 part_info = &all->img0;
1592 case SWITCHTEC_FW_PART_ID_G5_IMG1:
1593 inf->redundant = all->img_redundant_flag;
1594 part_info = &all->img1;
1596 case SWITCHTEC_FW_PART_ID_G5_CFG0:
1597 inf->redundant = all->cfg_redundant_flag;
1598 part_info = &all->cfg0;
1600 case SWITCHTEC_FW_PART_ID_G5_CFG1:
1601 inf->redundant = all->cfg_redundant_flag;
1602 part_info = &all->cfg1;
1604 case SWITCHTEC_FW_PART_ID_G5_NVLOG:
1605 part_info = &all->nvlog;
1607 case SWITCHTEC_FW_PART_ID_G5_SEEPROM:
1612 ret = switchtec_fw_info_metadata_gen5(dev, inf);
1614 inf->running =
true;
1624 inf->
part_addr = le32toh(part_info->part_start);
1625 inf->
part_len = le32toh(part_info->part_size_dw) * 4;
1626 inf->active = part_info->active;
1627 inf->running = part_info->is_using;
1628 inf->read_only = part_info->read_only;
1629 inf->valid = part_info->valid;
1633 return switchtec_fw_info_metadata_gen5(dev, inf);
1636static int switchtec_fw_part_info_gen6(
struct switchtec_dev *dev,
1640 struct switchtec_flash_part_info_gen4 *part_info;
1644 case SWITCHTEC_FW_PART_ID_G6_MAP0:
1645 part_info = &all->map0;
1647 case SWITCHTEC_FW_PART_ID_G6_MAP1:
1648 part_info = &all->map1;
1650 case SWITCHTEC_FW_PART_ID_G6_KEY0:
1651 inf->redundant = all->key_redundant_flag;
1652 part_info = &all->keyman0;
1654 case SWITCHTEC_FW_PART_ID_G6_KEY1:
1655 inf->redundant = all->key_redundant_flag;
1656 part_info = &all->keyman1;
1658 case SWITCHTEC_FW_PART_ID_G6_BL20:
1659 inf->redundant = all->bl2_redundant_flag;
1660 part_info = &all->bl20;
1662 case SWITCHTEC_FW_PART_ID_G6_BL21:
1663 inf->redundant = all->bl2_redundant_flag;
1664 part_info = &all->bl21;
1666 case SWITCHTEC_FW_PART_ID_G6_IMG0:
1667 inf->redundant = all->img_redundant_flag;
1668 part_info = &all->img0;
1670 case SWITCHTEC_FW_PART_ID_G6_IMG1:
1671 inf->redundant = all->img_redundant_flag;
1672 part_info = &all->img1;
1674 case SWITCHTEC_FW_PART_ID_G6_CFG0:
1675 inf->redundant = all->cfg_redundant_flag;
1676 part_info = &all->cfg0;
1678 case SWITCHTEC_FW_PART_ID_G6_CFG1:
1679 inf->redundant = all->cfg_redundant_flag;
1680 part_info = &all->cfg1;
1682 case SWITCHTEC_FW_PART_ID_G6_NVLOG:
1683 part_info = &all->nvlog;
1685 case SWITCHTEC_FW_PART_ID_G6_SEEPROM:
1690 ret = switchtec_fw_info_metadata_gen6(dev, inf);
1692 inf->running =
true;
1702 inf->
part_addr = le32toh(part_info->part_start);
1703 inf->
part_len = le32toh(part_info->part_size_dw) * 4;
1704 inf->active = part_info->active;
1705 inf->running = part_info->is_using;
1706 inf->read_only = part_info->read_only;
1707 inf->valid = part_info->valid;
1711 return switchtec_fw_info_metadata_gen6(dev, inf);
1728 uint8_t subcmd = MRPC_PART_INFO_GET_ALL_INFO;
1733 if (info == NULL || nr_info == 0)
1736 if (dev->gen == SWITCHTEC_GEN4) {
1738 sizeof(subcmd), &all_info_gen4,
1739 sizeof(all_info_gen4));
1742 all_info_gen4.firmware_version =
1743 le32toh(all_info_gen4.firmware_version);
1744 all_info_gen4.flash_size = le32toh(all_info_gen4.flash_size);
1745 all_info_gen4.device_id = le16toh(all_info_gen4.device_id);
1746 }
else if (dev->gen == SWITCHTEC_GEN5) {
1747 subcmd = MRPC_PART_INFO_GET_ALL_INFO_GEN5;
1749 sizeof(subcmd), &all_info_gen5,
1750 sizeof(all_info_gen5));
1753 all_info_gen5.firmware_version =
1754 le32toh(all_info_gen5.firmware_version);
1755 all_info_gen5.flash_size = le32toh(all_info_gen5.flash_size);
1756 all_info_gen5.device_id = le16toh(all_info_gen5.device_id);
1757 }
else if (dev->gen == SWITCHTEC_GEN6) {
1758 subcmd = MRPC_PART_INFO_GET_ALL_INFO_GEN6;
1760 sizeof(subcmd), &all_info_gen6,
1761 sizeof(all_info_gen6));
1764 all_info_gen6.firmware_version =
1765 le32toh(all_info_gen6.firmware_version);
1766 all_info_gen6.flash_size = le32toh(all_info_gen6.flash_size);
1767 all_info_gen6.device_id = le16toh(all_info_gen6.device_id);
1770 for (i = 0; i < nr_info; i++) {
1774 inf->
gen = dev->gen;
1775 inf->
type = switchtec_fw_id_to_type(inf);
1776 inf->active =
false;
1777 inf->running =
false;
1780 switch (info->
gen) {
1781 case SWITCHTEC_GEN3:
1782 ret = switchtec_fw_part_info_gen3(dev, inf);
1784 case SWITCHTEC_GEN4:
1785 ret = switchtec_fw_part_info_gen4(dev, inf,
1788 case SWITCHTEC_GEN5:
1789 ret = switchtec_fw_part_info_gen5(dev, inf,
1792 case SWITCHTEC_GEN6:
1793 ret = switchtec_fw_part_info_gen6(dev, inf,
1807 inf->metadata = NULL;
1832 .subcmd = MRPC_PART_INFO_GET_METADATA_GEN6,
1834 inf = malloc(
sizeof(*inf));
1837 memset(inf, 0,
sizeof(*inf));
1840 for (
int i = 0; i <= 9; i++) {
1841 metadata = malloc(
sizeof(*metadata));
1845 ret =
switchtec_cmd(dev, MRPC_PART_INFO, &subcmd,
sizeof(subcmd),
1846 metadata,
sizeof(*metadata));
1851 version_to_string(le32toh(metadata->version), inf->
version,
1853 inf->metadata = metadata;
1854 inf->next = malloc(
sizeof(*inf));
1857 memset(inf->next, 0,
sizeof(*inf));
1867int switchtec_get_device_id_bl2(
struct switchtec_dev *dev,
1868 unsigned short *device_id)
1871 uint8_t subcmd = MRPC_PART_INFO_GET_ALL_INFO;
1875 if (dev->gen != SWITCHTEC_GEN_UNKNOWN)
1879 sizeof(subcmd), &all_info,
1882 *device_id = le16toh(all_info.device_id);
1883 }
else if (ret == ERR_SUBCMD_INVALID) {
1884 subcmd = MRPC_PART_INFO_GET_ALL_INFO_GEN5;
1886 sizeof(subcmd), &all_info_gen5,
1887 sizeof(all_info_gen5));
1889 *device_id = le16toh(all_info_gen5.device_id);
1895static long multicfg_subcmd(
struct switchtec_dev *dev, uint32_t subcmd,
1901 subcmd |= index << 8;
1902 subcmd = htole32(subcmd);
1904 ret =
switchtec_cmd(dev, MRPC_MULTI_CFG, &subcmd,
sizeof(subcmd),
1905 &result,
sizeof(result));
1912static int get_multicfg(
struct switchtec_dev *dev,
1919 ret = multicfg_subcmd(dev, MRPC_MULTI_CFG_SUPPORTED, 0);
1928 ret = multicfg_subcmd(dev, MRPC_MULTI_CFG_COUNT, 0);
1935 for (i = 0; i < *nr_mult; i++) {
1936 info[i].
part_addr = multicfg_subcmd(dev,
1937 MRPC_MULTI_CFG_START_ADDR,
1939 info[i].
part_len = multicfg_subcmd(dev,
1940 MRPC_MULTI_CFG_LENGTH, i);
1941 strcpy(info[i].version,
"");
1946 ret = multicfg_subcmd(dev, MRPC_MULTI_CFG_ACTIVE, 0);
1951 info[ret].active = 1;
1956static const enum switchtec_fw_image_part_id_gen3
1957switchtec_fw_partitions_gen3[] = {
1958 SWITCHTEC_FW_PART_ID_G3_BOOT,
1959 SWITCHTEC_FW_PART_ID_G3_MAP0,
1960 SWITCHTEC_FW_PART_ID_G3_MAP1,
1961 SWITCHTEC_FW_PART_ID_G3_IMG0,
1962 SWITCHTEC_FW_PART_ID_G3_DAT0,
1963 SWITCHTEC_FW_PART_ID_G3_DAT1,
1964 SWITCHTEC_FW_PART_ID_G3_NVLOG,
1965 SWITCHTEC_FW_PART_ID_G3_IMG1,
1968static const enum switchtec_fw_image_part_id_gen4
1969switchtec_fw_partitions_gen4[] = {
1970 SWITCHTEC_FW_PART_ID_G4_MAP0,
1971 SWITCHTEC_FW_PART_ID_G4_MAP1,
1972 SWITCHTEC_FW_PART_ID_G4_KEY0,
1973 SWITCHTEC_FW_PART_ID_G4_KEY1,
1974 SWITCHTEC_FW_PART_ID_G4_BL20,
1975 SWITCHTEC_FW_PART_ID_G4_BL21,
1976 SWITCHTEC_FW_PART_ID_G4_CFG0,
1977 SWITCHTEC_FW_PART_ID_G4_CFG1,
1978 SWITCHTEC_FW_PART_ID_G4_IMG0,
1979 SWITCHTEC_FW_PART_ID_G4_IMG1,
1980 SWITCHTEC_FW_PART_ID_G4_NVLOG,
1981 SWITCHTEC_FW_PART_ID_G4_SEEPROM,
1984static const enum switchtec_fw_image_part_id_gen5
1985switchtec_fw_partitions_gen5[] = {
1986 SWITCHTEC_FW_PART_ID_G5_MAP0,
1987 SWITCHTEC_FW_PART_ID_G5_MAP1,
1988 SWITCHTEC_FW_PART_ID_G5_KEY0,
1989 SWITCHTEC_FW_PART_ID_G5_KEY1,
1990 SWITCHTEC_FW_PART_ID_G5_RIOT0,
1991 SWITCHTEC_FW_PART_ID_G5_RIOT1,
1992 SWITCHTEC_FW_PART_ID_G5_BL20,
1993 SWITCHTEC_FW_PART_ID_G5_BL21,
1994 SWITCHTEC_FW_PART_ID_G5_CFG0,
1995 SWITCHTEC_FW_PART_ID_G5_CFG1,
1996 SWITCHTEC_FW_PART_ID_G5_IMG0,
1997 SWITCHTEC_FW_PART_ID_G5_IMG1,
1998 SWITCHTEC_FW_PART_ID_G5_NVLOG,
1999 SWITCHTEC_FW_PART_ID_G5_SEEPROM,
2002static const enum switchtec_fw_image_part_id_gen6
2003switchtec_fw_partitions_gen6[] = {
2004 SWITCHTEC_FW_PART_ID_G6_MAP0,
2005 SWITCHTEC_FW_PART_ID_G6_MAP1,
2006 SWITCHTEC_FW_PART_ID_G6_KEY0,
2007 SWITCHTEC_FW_PART_ID_G6_KEY1,
2008 SWITCHTEC_FW_PART_ID_G6_BL20,
2009 SWITCHTEC_FW_PART_ID_G6_BL21,
2010 SWITCHTEC_FW_PART_ID_G6_CFG0,
2011 SWITCHTEC_FW_PART_ID_G6_CFG1,
2012 SWITCHTEC_FW_PART_ID_G6_IMG0,
2013 SWITCHTEC_FW_PART_ID_G6_IMG1,
2014 SWITCHTEC_FW_PART_ID_G6_NVLOG,
2015 SWITCHTEC_FW_PART_ID_G6_SEEPROM,
2018static struct switchtec_fw_part_type *
2022 switch (info->
type) {
2023 case SWITCHTEC_FW_TYPE_BOOT:
return &summary->boot;
2024 case SWITCHTEC_FW_TYPE_MAP:
return &summary->map;
2025 case SWITCHTEC_FW_TYPE_IMG:
return &summary->img;
2026 case SWITCHTEC_FW_TYPE_CFG:
return &summary->cfg;
2027 case SWITCHTEC_FW_TYPE_NVLOG:
return &summary->nvlog;
2028 case SWITCHTEC_FW_TYPE_SEEPROM:
return &summary->seeprom;
2029 case SWITCHTEC_FW_TYPE_KEY:
return &summary->key;
2030 case SWITCHTEC_FW_TYPE_BL2:
return &summary->bl2;
2031 case SWITCHTEC_FW_TYPE_RIOT:
return &summary->riot;
2032 default:
return NULL;
2046 uint32_t cmd = htole32(MRPC_PART_INFO_GET_SMS_FMC_VERSION_GEN6);
2049 if (!dev || !info) {
2055 info,
sizeof(*info));
2059 *info = le32toh(*info);
2069 struct switchtec_fw_part_type *type;
2070 int nr_info, nr_mcfg = 16;
2075 case SWITCHTEC_GEN3:
2076 nr_info = ARRAY_SIZE(switchtec_fw_partitions_gen3);
2078 case SWITCHTEC_GEN4:
2079 nr_info = ARRAY_SIZE(switchtec_fw_partitions_gen4);
2081 case SWITCHTEC_GEN5:
2082 nr_info = ARRAY_SIZE(switchtec_fw_partitions_gen5);
2084 case SWITCHTEC_GEN6:
2085 nr_info = ARRAY_SIZE(switchtec_fw_partitions_gen6);
2092 st_sz =
sizeof(*summary) +
sizeof(*summary->all) * (nr_info + nr_mcfg);
2094 summary = malloc(st_sz);
2098 memset(summary, 0, st_sz);
2099 summary->nr_info = nr_info;
2102 case SWITCHTEC_GEN3:
2103 for (i = 0; i < nr_info; i++)
2105 switchtec_fw_partitions_gen3[i];
2107 case SWITCHTEC_GEN4:
2108 for (i = 0; i < nr_info; i++)
2110 switchtec_fw_partitions_gen4[i];
2112 case SWITCHTEC_GEN5:
2113 for (i = 0; i < nr_info; i++)
2115 switchtec_fw_partitions_gen5[i];
2117 case SWITCHTEC_GEN6:
2118 for (i = 0; i < nr_info; i++)
2120 switchtec_fw_partitions_gen6[i];
2129 if (ret != nr_info) {
2134 ret = get_multicfg(dev, &summary->all[nr_info], &nr_mcfg);
2140 for (i = 0; i < nr_info; i++) {
2141 type = switchtec_fw_type_ptr(summary, &summary->all[i]);
2146 if (summary->all[i].active)
2147 type->active = &summary->all[i];
2149 type->inactive = &summary->all[i];
2152 infp = &summary->mult_cfg;
2153 for (; i < nr_info + nr_mcfg; i++) {
2154 *infp = &summary->all[i];
2155 infp = &summary->all[i].next;
2169 for (i = 0; i < summary->nr_info; i++)
2170 free(summary->all[i].metadata);
2184 free(inf->metadata);
2205 size_t len,
void *buf)
2212 unsigned char *cbuf = buf;
2216 size_t chunk_len = len;
2217 if (chunk_len > MRPC_MAX_DATA_LEN-8)
2218 chunk_len = MRPC_MAX_DATA_LEN-8;
2220 cmd.addr = htole32(addr);
2221 cmd.length = htole32(chunk_len);
2249 unsigned long addr,
size_t len,
2250 void (*progress_callback)(
int cur,
int tot))
2253 unsigned char buf[(MRPC_MAX_DATA_LEN-8)*4];
2255 size_t total_len = len;
2260 size_t chunk_len = len;
2261 if (chunk_len >
sizeof(buf))
2262 chunk_len =
sizeof(buf);
2269 while (total_wrote < ret) {
2270 wrote = write(fd, &buf[total_wrote],
2274 total_wrote += wrote;
2281 if (progress_callback)
2282 progress_callback(read, total_len);
2299 void (*progress_callback)(
int cur,
int tot))
2306static int switchtec_fw_img_write_hdr_gen3(
int fd,
2312 memcpy(hdr.magic, ftr->magic,
sizeof(hdr.magic));
2313 hdr.image_len = ftr->image_len;
2315 hdr.load_addr = ftr->load_addr;
2316 hdr.version = ftr->version;
2317 hdr.header_crc = ftr->header_crc;
2318 hdr.image_crc = ftr->image_crc;
2320 if (hdr.type == SWITCHTEC_FW_PART_ID_G3_MAP1)
2321 hdr.type = SWITCHTEC_FW_PART_ID_G3_MAP0;
2322 else if (hdr.type == SWITCHTEC_FW_PART_ID_G3_IMG1)
2323 hdr.type = SWITCHTEC_FW_PART_ID_G3_IMG0;
2324 else if (hdr.type == SWITCHTEC_FW_PART_ID_G3_DAT1)
2325 hdr.type = SWITCHTEC_FW_PART_ID_G3_DAT0;
2327 return write(fd, &hdr,
sizeof(hdr));
2330static int switchtec_fw_img_write_hdr_gen4(
int fd,
2336 ret = write(fd, hdr,
sizeof(*hdr));
2358 switch (info->
gen) {
2359 case SWITCHTEC_GEN3:
return switchtec_fw_img_write_hdr_gen3(fd, info);
2360 case SWITCHTEC_GEN4:
2361 case SWITCHTEC_GEN5:
2362 case SWITCHTEC_GEN6:
return switchtec_fw_img_write_hdr_gen4(fd, info);
2385 .subcmd = MRPC_FWDNLD_BOOT_RO,
2391 uint8_t reserved[3];
2401 ret =
switchtec_cmd(dev, MRPC_FWDNLD, &subcmd,
sizeof(subcmd),
2402 &result,
sizeof(result));
2404 if (ret == ERR_SUBCMD_INVALID) {
2412 return result.status;
2425 .subcmd = MRPC_FWDNLD_BOOT_RO,
2435 return switchtec_cmd(dev, MRPC_FWDNLD, &subcmd,
sizeof(subcmd),
int switchtec_cmd(struct switchtec_dev *dev, uint32_t cmd, const void *payload, size_t payload_len, void *resp, size_t resp_len)
Execute an MRPC command.
enum switchtec_gen switchtec_fw_version_to_gen(unsigned int version)
Extract generation information from FW version number.
int switchtec_fw_img_get(struct switchtec_dev *dev, int fd, enum switchtec_fw_type_gen6 fw_type, int fw_slot, void(*progress_callback)(int cur, int tot))
Download fwimg file from device.
int switchtec_fw_img_write_hdr(int fd, struct switchtec_fw_image_info *info)
Write the header for a Switchtec firmware image file.
int switchtec_fw_read(struct switchtec_dev *dev, unsigned long addr, size_t len, void *buf)
Read a Switchtec device's flash data.
int switchtec_fw_body_read_fd(struct switchtec_dev *dev, int fd, struct switchtec_fw_image_info *info, void(*progress_callback)(int cur, int tot))
Read a Switchtec device's flash image body into a file.
int switchtec_fw_file_secure_version_newer(struct switchtec_dev *dev, int img_fd)
Check if the secure version of an image file is newer than that of the image on device.
int switchtec_fw_read_fd(struct switchtec_dev *dev, int fd, unsigned long addr, size_t len, void(*progress_callback)(int cur, int tot))
Read a Switchtec device's flash data into a file.
struct switchtec_fw_image_info * switchtec_fw_part_data_bl2(struct switchtec_dev *dev)
Return the firmware image information using supported metadata MRPC commands for the gen6 BL2 phase.
int switchtec_sms_fmc_version_get(struct switchtec_dev *dev, uint32_t *info)
Return firmware summary information structure for the flash partitfons in the device.
int switchtec_fw_is_boot_ro(struct switchtec_dev *dev)
Check if the boot partition is marked as read-only.
int switchtec_fw_file_info(int fd, struct switchtec_fw_image_info *info)
Retrieve information about a firmware image file.
int switchtec_fw_write_fd(struct switchtec_dev *dev, int img_fd, int dont_activate, int force, void(*progress_callback)(int cur, int tot))
Write a firmware file to the switchtec device.
void switchtec_fw_perror(const char *s, int ret)
Print an error string to stdout.
void switchtec_fw_image_info_free(struct switchtec_fw_image_info *inf)
Free a firmware image info data structure.
static int switchtec_fw_part_info(struct switchtec_dev *dev, int nr_info, struct switchtec_fw_image_info *info)
Return firmware information structures for a number of firmware partitions.
int switchtec_fw_set_boot_ro(struct switchtec_dev *dev, enum switchtec_fw_ro ro)
Set or clear a boot partition's read-only flag.
void switchtec_fw_part_summary_free(struct switchtec_fw_part_summary *summary)
Free a firmware part summary data structure.
int switchtec_fw_set_redundant_flag(struct switchtec_dev *dev, int keyman, int riot, int bl2, int cfg, int fw, int set)
Set the redundant image flag for the specified image types.
int switchtec_fw_toggle_active_partition(struct switchtec_dev *dev, int toggle_bl2, int toggle_key, int toggle_fw, int toggle_cfg, int toggle_riotcore)
Toggle the active firmware partition for the main or configuration images.
const char * switchtec_fw_image_type(const struct switchtec_fw_image_info *info)
Return a string describing the type of a firmware image.
int switchtec_fw_write_file(struct switchtec_dev *dev, FILE *fimg, int dont_activate, int force, void(*progress_callback)(int cur, int tot))
Write a firmware file to the switchtec device.
int switchtec_flash_part(struct switchtec_dev *dev, struct switchtec_fw_image_info *info, enum switchtec_fw_image_part_id_gen3 part)
Retrieve information about a flash partition.
int switchtec_sn_ver_get(struct switchtec_dev *dev, struct switchtec_sn_ver_info *info)
Get serial number and security version.
Information about a firmware image or partition.
enum switchtec_gen gen
Image generation.
size_t part_body_offset
Partition image body offset.
unsigned long image_crc
CRC checksum of the image.
char version[32]
Firmware/Config version.
size_t image_len
Length of the image.
unsigned long part_id
Image partition ID.
size_t part_addr
Address of the partition.
size_t part_len
Length of the partition.
enum switchtec_fw_type type
Image partition type.
switchtec_fw_ro
Flag which indicates if a partition is read-only or not.
switchtec_gen
The PCIe generations.
static int switchtec_is_gen6(struct switchtec_dev *dev)
Return whether a Switchtec device is a Gen 6 device.
switchtec_boot_phase
Device boot phase.
static int switchtec_is_gen5(struct switchtec_dev *dev)
Return whether a Switchtec device is a Gen 5 device.
switchtec_fw_dlstatus
Firmware update status.
static int switchtec_is_gen3(struct switchtec_dev *dev)
Return whether a Switchtec device is a Gen 3 device.