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" 66 enum 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,
81 uint32_t secure_version;
83 uint32_t metadata_len;
95 uint8_t public_key_modulus[512];
96 uint8_t public_key_exponent[4];
100 uint8_t bist_gpio_pin_cfg;
101 uint8_t bist_gpio_level_cfg;
103 uint32_t xml_version;
104 uint32_t relocatable_img_len;
122 enum mrpc_bg_status *bgstatus)
124 uint32_t cmd = MRPC_FWDNLD;
125 uint32_t subcmd = MRPC_FWDNLD_GET_STATUS;
137 &result,
sizeof(result));
143 *status = result.dlstatus;
145 if (bgstatus != NULL)
146 *bgstatus = result.bgstatus;
151 static int switchtec_fw_wait(
struct switchtec_dev *dev,
154 enum mrpc_bg_status bgstatus;
164 if (*status != SWITCHTEC_DLSTAT_INPROGRESS &&
165 *status != SWITCHTEC_DLSTAT_COMPLETES &&
166 *status != SWITCHTEC_DLSTAT_SUCCESS_FIRM_ACT &&
167 *status != SWITCHTEC_DLSTAT_SUCCESS_DATA_ACT)
169 if (bgstatus == MRPC_BG_STAT_ERROR)
170 return SWITCHTEC_DLSTAT_HARDWARE_ERR;
172 }
while (bgstatus == MRPC_BG_STAT_INPROGRESS);
188 int toggle_bl2,
int toggle_key,
189 int toggle_fw,
int toggle_cfg)
202 cmd.subcmd = MRPC_FW_TX_TOGGLE;
204 cmd_id = MRPC_FWDNLD;
205 cmd.subcmd = MRPC_FWDNLD_TOGGLE;
208 cmd.toggle_bl2 = !!toggle_bl2;
209 cmd.toggle_key = !!toggle_key;
210 cmd.toggle_fw = !!toggle_fw;
211 cmd.toggle_cfg = !!toggle_cfg;
217 static enum switchtec_fw_part_type_gen4
218 switchtec_fw_type_gen4(
enum switchtec_fw_type type)
221 case SWITCHTEC_FW_TYPE_MAP:
222 return SWITCHTEC_FW_IMG_TYPE_MAP_GEN4;
223 case SWITCHTEC_FW_TYPE_IMG:
224 return SWITCHTEC_FW_IMG_TYPE_IMG_GEN4;
225 case SWITCHTEC_FW_TYPE_CFG:
226 return SWITCHTEC_FW_IMG_TYPE_CFG_GEN4;
227 case SWITCHTEC_FW_TYPE_NVLOG:
228 return SWITCHTEC_FW_IMG_TYPE_NVLOG_GEN4;
229 case SWITCHTEC_FW_TYPE_SEEPROM:
230 return SWITCHTEC_FW_IMG_TYPE_SEEPROM_GEN4;
231 case SWITCHTEC_FW_TYPE_KEY:
232 return SWITCHTEC_FW_IMG_TYPE_KEYMAN_GEN4;
233 case SWITCHTEC_FW_TYPE_BL2:
234 return SWITCHTEC_FW_IMG_TYPE_BL2_GEN4;
236 return SWITCHTEC_FW_IMG_TYPE_UNKNOWN_GEN4;
250 enum switchtec_fw_redundancy redund,
251 enum switchtec_fw_type type)
255 struct set_fw_redundancy{
261 .sub_cmd = MRPC_FWDNLD_SET_REDUNDANCY,
262 .part_type = switchtec_fw_type_gen4(type),
271 ret =
switchtec_cmd(dev, MRPC_FWDNLD, &cmd,
sizeof(cmd), NULL, 0);
279 uint8_t dont_activate;
285 uint8_t data[MRPC_MAX_DATA_LEN -
sizeof(
struct cmd_fwdl_hdr)];
300 int dont_activate,
int force,
301 void (*progress_callback)(
int cur,
int tot))
304 enum mrpc_bg_status bgstatus;
305 ssize_t image_size, offset = 0;
308 uint32_t cmd_id = MRPC_FWDNLD;
313 image_size = lseek(img_fd, 0, SEEK_END);
316 lseek(img_fd, 0, SEEK_SET);
320 if (!force && status == SWITCHTEC_DLSTAT_INPROGRESS) {
325 if (bgstatus == MRPC_BG_STAT_INPROGRESS) {
331 cmd.hdr.subcmd = MRPC_FW_TX_FLASH;
333 cmd.hdr.subcmd = MRPC_FWDNLD_DOWNLOAD;
335 cmd.hdr.dont_activate = !!dont_activate;
336 cmd.hdr.img_length = htole32(image_size);
338 while (offset < image_size) {
339 ssize_t blklen = read(img_fd, &cmd.data,
342 if (blklen == -EAGAIN || blklen == -EWOULDBLOCK)
351 cmd.hdr.offset = htole32(offset);
352 cmd.hdr.blk_length = htole32(blklen);
360 ret = switchtec_fw_wait(dev, &status);
364 offset += cmd.hdr.blk_length;
366 if (progress_callback)
367 progress_callback(offset, image_size);
371 if (status == SWITCHTEC_DLSTAT_COMPLETES)
374 if (status == SWITCHTEC_DLSTAT_SUCCESS_FIRM_ACT)
377 if (status == SWITCHTEC_DLSTAT_SUCCESS_DATA_ACT)
381 return SWITCHTEC_DLSTAT_HARDWARE_ERR;
398 int dont_activate,
int force,
399 void (*progress_callback)(
int cur,
int tot))
402 enum mrpc_bg_status bgstatus;
403 ssize_t image_size, offset = 0;
406 uint32_t cmd_id = MRPC_FWDNLD;
411 ret = fseek(fimg, 0, SEEK_END);
414 image_size = ftell(fimg);
417 ret = fseek(fimg, 0, SEEK_SET);
423 if (!force && status == SWITCHTEC_DLSTAT_INPROGRESS) {
428 if (bgstatus == MRPC_BG_STAT_INPROGRESS) {
434 cmd.hdr.subcmd = MRPC_FW_TX_FLASH;
436 cmd.hdr.subcmd = MRPC_FWDNLD_DOWNLOAD;
438 cmd.hdr.dont_activate = !!dont_activate;
439 cmd.hdr.img_length = htole32(image_size);
441 while (offset < image_size) {
442 ssize_t blklen = fread(&cmd.data, 1,
sizeof(cmd.data), fimg);
451 cmd.hdr.offset = htole32(offset);
452 cmd.hdr.blk_length = htole32(blklen);
460 ret = switchtec_fw_wait(dev, &status);
464 offset += cmd.hdr.blk_length;
466 if (progress_callback)
467 progress_callback(offset, image_size);
470 if (status == SWITCHTEC_DLSTAT_COMPLETES)
473 if (status == SWITCHTEC_DLSTAT_SUCCESS_FIRM_ACT)
476 if (status == SWITCHTEC_DLSTAT_SUCCESS_DATA_ACT)
480 return SWITCHTEC_DLSTAT_HARDWARE_ERR;
503 case SWITCHTEC_DLSTAT_HEADER_INCORRECT:
504 msg =
"Header incorrect";
break;
505 case SWITCHTEC_DLSTAT_OFFSET_INCORRECT:
506 msg =
"Offset incorrect";
break;
507 case SWITCHTEC_DLSTAT_CRC_INCORRECT:
508 msg =
"CRC incorrect";
break;
509 case SWITCHTEC_DLSTAT_LENGTH_INCORRECT:
510 msg =
"Length incorrect";
break;
511 case SWITCHTEC_DLSTAT_HARDWARE_ERR:
512 msg =
"Hardware Error";
break;
513 case SWITCHTEC_DLSTAT_DOWNLOAD_TIMEOUT:
514 msg =
"Download Timeout";
break;
515 case SWITCHTEC_DLSTAT_NO_FILE:
516 msg =
"No Image Transferred";
break;
518 fprintf(stderr,
"%s: Unknown Error (0x%x)\n", s, ret);
522 fprintf(stderr,
"%s: %s\n", s, msg);
525 static enum switchtec_fw_type
528 switch ((
unsigned long)info->
part_id) {
529 case SWITCHTEC_FW_PART_ID_G3_BOOT:
return SWITCHTEC_FW_TYPE_BOOT;
530 case SWITCHTEC_FW_PART_ID_G3_MAP0:
return SWITCHTEC_FW_TYPE_MAP;
531 case SWITCHTEC_FW_PART_ID_G3_MAP1:
return SWITCHTEC_FW_TYPE_MAP;
532 case SWITCHTEC_FW_PART_ID_G3_IMG0:
return SWITCHTEC_FW_TYPE_IMG;
533 case SWITCHTEC_FW_PART_ID_G3_IMG1:
return SWITCHTEC_FW_TYPE_IMG;
534 case SWITCHTEC_FW_PART_ID_G3_DAT0:
return SWITCHTEC_FW_TYPE_CFG;
535 case SWITCHTEC_FW_PART_ID_G3_DAT1:
return SWITCHTEC_FW_TYPE_CFG;
536 case SWITCHTEC_FW_PART_ID_G3_NVLOG:
return SWITCHTEC_FW_TYPE_NVLOG;
537 case SWITCHTEC_FW_PART_ID_G3_SEEPROM:
return SWITCHTEC_FW_TYPE_SEEPROM;
540 case 0xa8000000:
return SWITCHTEC_FW_TYPE_BOOT;
541 case 0xa8020000:
return SWITCHTEC_FW_TYPE_MAP;
542 case 0xa8060000:
return SWITCHTEC_FW_TYPE_IMG;
543 case 0xa8210000:
return SWITCHTEC_FW_TYPE_CFG;
545 default:
return SWITCHTEC_FW_TYPE_UNKNOWN;
549 static enum switchtec_fw_type
553 case SWITCHTEC_FW_PART_ID_G4_MAP0:
return SWITCHTEC_FW_TYPE_MAP;
554 case SWITCHTEC_FW_PART_ID_G4_MAP1:
return SWITCHTEC_FW_TYPE_MAP;
555 case SWITCHTEC_FW_PART_ID_G4_KEY0:
return SWITCHTEC_FW_TYPE_KEY;
556 case SWITCHTEC_FW_PART_ID_G4_KEY1:
return SWITCHTEC_FW_TYPE_KEY;
557 case SWITCHTEC_FW_PART_ID_G4_BL20:
return SWITCHTEC_FW_TYPE_BL2;
558 case SWITCHTEC_FW_PART_ID_G4_BL21:
return SWITCHTEC_FW_TYPE_BL2;
559 case SWITCHTEC_FW_PART_ID_G4_CFG0:
return SWITCHTEC_FW_TYPE_CFG;
560 case SWITCHTEC_FW_PART_ID_G4_CFG1:
return SWITCHTEC_FW_TYPE_CFG;
561 case SWITCHTEC_FW_PART_ID_G4_IMG0:
return SWITCHTEC_FW_TYPE_IMG;
562 case SWITCHTEC_FW_PART_ID_G4_IMG1:
return SWITCHTEC_FW_TYPE_IMG;
563 case SWITCHTEC_FW_PART_ID_G4_NVLOG:
return SWITCHTEC_FW_TYPE_NVLOG;
564 case SWITCHTEC_FW_PART_ID_G4_SEEPROM:
return SWITCHTEC_FW_TYPE_SEEPROM;
565 default:
return SWITCHTEC_FW_TYPE_UNKNOWN;
569 static enum switchtec_fw_type
573 case SWITCHTEC_GEN3:
return switchtec_fw_id_to_type_gen3(info);
574 case SWITCHTEC_GEN4:
return switchtec_fw_id_to_type_gen4(info);
575 default:
return SWITCHTEC_FW_TYPE_UNKNOWN;
579 static int switchtec_fw_file_info_gen3(
int fd,
585 ret = read(fd, &hdr,
sizeof(hdr));
586 lseek(fd, 0, SEEK_SET);
588 if (ret !=
sizeof(hdr))
591 if (strcmp(hdr.magic,
"PMC") != 0)
597 info->
gen = SWITCHTEC_GEN3;
599 info->
image_crc = le32toh(hdr.image_crc);
600 version_to_string(hdr.version, info->
version,
sizeof(info->
version));
601 info->
image_len = le32toh(hdr.image_len);
603 info->
type = switchtec_fw_id_to_type(info);
605 info->secure_version = 0;
614 static int switchtec_fw_file_info_gen4(
int fd,
620 ret = read(fd, &hdr,
sizeof(hdr));
621 lseek(fd, 0, SEEK_SET);
623 if (ret !=
sizeof(hdr))
626 if (strncmp(hdr.magic,
"MSCC",
sizeof(hdr.magic)))
629 if (strncmp(hdr.sub_magic,
"_MD ",
sizeof(hdr.sub_magic)))
635 info->
gen = SWITCHTEC_GEN4;
638 case SWITCHTEC_FW_IMG_TYPE_MAP_GEN4:
639 info->
part_id = SWITCHTEC_FW_PART_ID_G4_MAP0;
641 case SWITCHTEC_FW_IMG_TYPE_KEYMAN_GEN4:
642 info->
part_id = SWITCHTEC_FW_PART_ID_G4_KEY0;
644 case SWITCHTEC_FW_IMG_TYPE_BL2_GEN4:
645 info->
part_id = SWITCHTEC_FW_PART_ID_G4_BL20;
647 case SWITCHTEC_FW_IMG_TYPE_CFG_GEN4:
648 info->
part_id = SWITCHTEC_FW_PART_ID_G4_CFG0;
650 case SWITCHTEC_FW_IMG_TYPE_IMG_GEN4:
651 info->
part_id = SWITCHTEC_FW_PART_ID_G4_IMG0;
653 case SWITCHTEC_FW_IMG_TYPE_NVLOG_GEN4:
654 info->
part_id = SWITCHTEC_FW_PART_ID_G4_NVLOG;
656 case SWITCHTEC_FW_IMG_TYPE_SEEPROM_GEN4:
657 info->
part_id = SWITCHTEC_FW_PART_ID_G4_SEEPROM;
663 info->
image_crc = le32toh(hdr.image_crc);
664 version_to_string(hdr.version, info->
version,
sizeof(info->
version));
665 info->
image_len = le32toh(hdr.image_len);
667 info->
type = switchtec_fw_id_to_type(info);
669 info->secure_version = le32toh(hdr.secure_version);
688 ret = read(fd, &magic,
sizeof(magic));
689 lseek(fd, 0, SEEK_SET);
691 if (ret !=
sizeof(magic)) {
696 if (!strncmp(magic,
"PMC",
sizeof(magic))) {
697 switchtec_fw_file_info_gen3(fd, info);
698 }
else if (!strncmp(magic,
"MSCC",
sizeof(magic))) {
699 switchtec_fw_file_info_gen4(fd, info);
732 sn_info.ver_bl2 = 0xffffffff;
733 sn_info.ver_main = 0xffffffff;
734 sn_info.ver_km = 0xffffffff;
738 case SWITCHTEC_FW_TYPE_BL2:
739 if (info.secure_version > sn_info.ver_bl2)
743 case SWITCHTEC_FW_TYPE_IMG:
744 if (info.secure_version > sn_info.ver_main)
748 case SWITCHTEC_FW_TYPE_KEY:
749 if (info.secure_version > sn_info.ver_km)
767 switch (info->
type) {
768 case SWITCHTEC_FW_TYPE_BOOT:
return "BOOT";
769 case SWITCHTEC_FW_TYPE_MAP:
return "MAP";
770 case SWITCHTEC_FW_TYPE_IMG:
return "IMG";
771 case SWITCHTEC_FW_TYPE_CFG:
return "CFG";
772 case SWITCHTEC_FW_TYPE_KEY:
return "KEY";
773 case SWITCHTEC_FW_TYPE_BL2:
return "BL2";
774 case SWITCHTEC_FW_TYPE_NVLOG:
return "NVLOG";
775 case SWITCHTEC_FW_TYPE_SEEPROM:
return "SEEPROM";
776 default:
return "UNKNOWN";
780 static int switchtec_fw_map_get_active(
struct switchtec_dev *dev,
783 uint32_t map0_update_index;
784 uint32_t map1_update_index;
788 sizeof(uint32_t), &map0_update_index);
793 sizeof(uint32_t), &map1_update_index);
798 if (map0_update_index < map1_update_index) {
799 if (info->
part_addr == SWITCHTEC_FLASH_MAP0_PART_START)
802 if (info->
part_addr == SWITCHTEC_FLASH_MAP1_PART_START)
809 static int switchtec_fw_info_metadata_gen3(
struct switchtec_dev *dev,
816 if (inf->
part_id == SWITCHTEC_FW_PART_ID_G3_NVLOG)
819 metadata = malloc(
sizeof(*metadata));
829 if (strncmp(metadata->magic,
"PMC",
sizeof(metadata->magic)))
832 version_to_string(metadata->version, inf->
version,
837 inf->metadata = metadata;
846 static int switchtec_fw_part_info_gen3(
struct switchtec_dev *dev,
854 case SWITCHTEC_FW_PART_ID_G3_BOOT:
855 inf->
part_addr = SWITCHTEC_FLASH_BOOT_PART_START;
856 inf->
part_len = SWITCHTEC_FLASH_PART_LEN;
859 case SWITCHTEC_FW_PART_ID_G3_MAP0:
860 inf->
part_addr = SWITCHTEC_FLASH_MAP0_PART_START;
861 inf->
part_len = SWITCHTEC_FLASH_PART_LEN;
862 ret = switchtec_fw_map_get_active(dev, inf);
864 case SWITCHTEC_FW_PART_ID_G3_MAP1:
865 inf->
part_addr = SWITCHTEC_FLASH_MAP1_PART_START;
866 inf->
part_len = SWITCHTEC_FLASH_PART_LEN;
867 ret = switchtec_fw_map_get_active(dev, inf);
871 inf->read_only =
false;
879 if (inf->
part_id == SWITCHTEC_FW_PART_ID_G3_NVLOG)
882 return switchtec_fw_info_metadata_gen3(dev, inf);
885 static int switchtec_fw_info_metadata_gen4(
struct switchtec_dev *dev,
893 .subcmd = MRPC_PART_INFO_GET_METADATA,
898 if (inf->
part_id == SWITCHTEC_FW_PART_ID_G4_NVLOG)
901 metadata = malloc(
sizeof(*metadata));
905 ret =
switchtec_cmd(dev, MRPC_PART_INFO, &subcmd,
sizeof(subcmd),
906 metadata,
sizeof(*metadata));
910 if (strncmp(metadata->magic,
"MSCC",
sizeof(metadata->magic)))
913 if (strncmp(metadata->sub_magic,
"_MD ",
sizeof(metadata->sub_magic)))
916 version_to_string(metadata->version, inf->
version,
921 inf->metadata = metadata;
931 uint32_t firmware_version;
936 uint8_t running_bl2_flag;
937 uint8_t running_cfg_flag;
938 uint8_t running_img_flag;
939 uint8_t running_key_flag;
940 uint8_t redundancy_key_flag;
941 uint8_t redundancy_bl2_flag;
942 uint8_t redundancy_cfg_flag;
943 uint8_t redundancy_img_flag;
948 uint16_t image_version;
953 uint32_t part_offset;
954 uint32_t part_size_dw;
958 } map0, map1, keyman0, keyman1, bl20, bl21, cfg0, cfg1,
959 img0, img1, nvlog, vendor[8];
962 static int switchtec_fw_part_info_gen4(
struct switchtec_dev *dev,
969 case SWITCHTEC_FW_PART_ID_G4_MAP0:
970 part_info = &all->map0;
972 case SWITCHTEC_FW_PART_ID_G4_MAP1:
973 part_info = &all->map1;
975 case SWITCHTEC_FW_PART_ID_G4_KEY0:
976 part_info = &all->keyman0;
977 inf->redundant = all->redundancy_key_flag;
979 case SWITCHTEC_FW_PART_ID_G4_KEY1:
980 part_info = &all->keyman1;
981 inf->redundant = all->redundancy_key_flag;
983 case SWITCHTEC_FW_PART_ID_G4_BL20:
984 part_info = &all->bl20;
985 inf->redundant = all->redundancy_bl2_flag;
987 case SWITCHTEC_FW_PART_ID_G4_BL21:
988 part_info = &all->bl21;
989 inf->redundant = all->redundancy_bl2_flag;
991 case SWITCHTEC_FW_PART_ID_G4_IMG0:
992 part_info = &all->img0;
993 inf->redundant = all->redundancy_img_flag;
995 case SWITCHTEC_FW_PART_ID_G4_IMG1:
996 part_info = &all->img1;
997 inf->redundant = all->redundancy_img_flag;
999 case SWITCHTEC_FW_PART_ID_G4_CFG0:
1000 part_info = &all->cfg0;
1001 inf->redundant = all->redundancy_cfg_flag;
1003 case SWITCHTEC_FW_PART_ID_G4_CFG1:
1004 part_info = &all->cfg1;
1005 inf->redundant = all->redundancy_cfg_flag;
1007 case SWITCHTEC_FW_PART_ID_G4_NVLOG:
1008 part_info = &all->nvlog;
1016 inf->
part_len = part_info->part_size_dw * 4;
1017 inf->active = part_info->active;
1018 inf->running = part_info->is_using;
1019 inf->read_only = part_info->read_only;
1020 inf->valid = part_info->valid;
1024 return switchtec_fw_info_metadata_gen4(dev, inf);
1041 uint8_t subcmd = MRPC_PART_INFO_GET_ALL_INFO;
1044 if (info == NULL || nr_info == 0)
1047 if (dev->gen == SWITCHTEC_GEN4) {
1049 sizeof(subcmd), &all_info,
1055 for (i = 0; i < nr_info; i++) {
1059 inf->
gen = dev->gen;
1060 inf->
type = switchtec_fw_id_to_type(inf);
1061 inf->active =
false;
1062 inf->running =
false;
1065 switch (info->
gen) {
1066 case SWITCHTEC_GEN3:
1067 ret = switchtec_fw_part_info_gen3(dev, inf);
1069 case SWITCHTEC_GEN4:
1070 ret = switchtec_fw_part_info_gen4(dev, inf, &all_info);
1083 inf->metadata = NULL;
1090 static long multicfg_subcmd(
struct switchtec_dev *dev, uint32_t subcmd,
1096 subcmd |= index << 8;
1098 ret =
switchtec_cmd(dev, MRPC_MULTI_CFG, &subcmd,
sizeof(subcmd),
1099 &result,
sizeof(result));
1106 static int get_multicfg(
struct switchtec_dev *dev,
1113 ret = multicfg_subcmd(dev, MRPC_MULTI_CFG_SUPPORTED, 0);
1122 ret = multicfg_subcmd(dev, MRPC_MULTI_CFG_COUNT, 0);
1129 for (i = 0; i < *nr_mult; i++) {
1130 info[i].
part_addr = multicfg_subcmd(dev,
1131 MRPC_MULTI_CFG_START_ADDR,
1133 info[i].
part_len = multicfg_subcmd(dev,
1134 MRPC_MULTI_CFG_LENGTH, i);
1140 ret = multicfg_subcmd(dev, MRPC_MULTI_CFG_ACTIVE, 0);
1145 info[ret].active = 1;
1150 static const enum switchtec_fw_image_part_id_gen3
1151 switchtec_fw_partitions_gen3[] = {
1152 SWITCHTEC_FW_PART_ID_G3_BOOT,
1153 SWITCHTEC_FW_PART_ID_G3_MAP0,
1154 SWITCHTEC_FW_PART_ID_G3_MAP1,
1155 SWITCHTEC_FW_PART_ID_G3_IMG0,
1156 SWITCHTEC_FW_PART_ID_G3_DAT0,
1157 SWITCHTEC_FW_PART_ID_G3_DAT1,
1158 SWITCHTEC_FW_PART_ID_G3_NVLOG,
1159 SWITCHTEC_FW_PART_ID_G3_IMG1,
1162 static const enum switchtec_fw_image_part_id_gen4
1163 switchtec_fw_partitions_gen4[] = {
1164 SWITCHTEC_FW_PART_ID_G4_MAP0,
1165 SWITCHTEC_FW_PART_ID_G4_MAP1,
1166 SWITCHTEC_FW_PART_ID_G4_KEY0,
1167 SWITCHTEC_FW_PART_ID_G4_KEY1,
1168 SWITCHTEC_FW_PART_ID_G4_BL20,
1169 SWITCHTEC_FW_PART_ID_G4_BL21,
1170 SWITCHTEC_FW_PART_ID_G4_CFG0,
1171 SWITCHTEC_FW_PART_ID_G4_CFG1,
1172 SWITCHTEC_FW_PART_ID_G4_IMG0,
1173 SWITCHTEC_FW_PART_ID_G4_IMG1,
1174 SWITCHTEC_FW_PART_ID_G4_NVLOG,
1177 static struct switchtec_fw_part_type *
1181 switch (info->
type) {
1182 case SWITCHTEC_FW_TYPE_BOOT:
return &summary->boot;
1183 case SWITCHTEC_FW_TYPE_MAP:
return &summary->map;
1184 case SWITCHTEC_FW_TYPE_IMG:
return &summary->img;
1185 case SWITCHTEC_FW_TYPE_CFG:
return &summary->cfg;
1186 case SWITCHTEC_FW_TYPE_NVLOG:
return &summary->nvlog;
1187 case SWITCHTEC_FW_TYPE_SEEPROM:
return &summary->seeprom;
1188 case SWITCHTEC_FW_TYPE_KEY:
return &summary->key;
1189 case SWITCHTEC_FW_TYPE_BL2:
return &summary->bl2;
1190 default:
return NULL;
1207 struct switchtec_fw_part_type *type;
1208 int nr_info, nr_mcfg = 16;
1213 case SWITCHTEC_GEN3:
1214 nr_info = ARRAY_SIZE(switchtec_fw_partitions_gen3);
1216 case SWITCHTEC_GEN4:
1217 nr_info = ARRAY_SIZE(switchtec_fw_partitions_gen4);
1224 st_sz =
sizeof(*summary) +
sizeof(*summary->all) * (nr_info + nr_mcfg);
1226 summary = malloc(st_sz);
1230 memset(summary, 0, st_sz);
1231 summary->nr_info = nr_info;
1234 case SWITCHTEC_GEN3:
1235 for (i = 0; i < nr_info; i++)
1237 switchtec_fw_partitions_gen3[i];
1239 case SWITCHTEC_GEN4:
1240 for (i = 0; i < nr_info; i++)
1242 switchtec_fw_partitions_gen4[i];
1250 if (ret != nr_info) {
1255 ret = get_multicfg(dev, &summary->all[nr_info], &nr_mcfg);
1261 for (i = 0; i < nr_info; i++) {
1262 type = switchtec_fw_type_ptr(summary, &summary->all[i]);
1263 if (summary->all[i].active)
1264 type->active = &summary->all[i];
1266 type->inactive = &summary->all[i];
1269 infp = &summary->mult_cfg;
1270 for (; i < nr_info + nr_mcfg; i++) {
1271 *infp = &summary->all[i];
1272 infp = &summary->all[i].next;
1286 for (i = 0; i < summary->nr_info; i++)
1287 free(summary->all[i].metadata);
1301 size_t len,
void *buf)
1308 unsigned char *cbuf = buf;
1312 size_t chunk_len = len;
1313 if (chunk_len > MRPC_MAX_DATA_LEN-8)
1314 chunk_len = MRPC_MAX_DATA_LEN-8;
1316 cmd.addr = htole32(addr);
1317 cmd.length = htole32(chunk_len);
1345 unsigned long addr,
size_t len,
1346 void (*progress_callback)(
int cur,
int tot))
1349 unsigned char buf[(MRPC_MAX_DATA_LEN-8)*4];
1351 size_t total_len = len;
1356 size_t chunk_len = len;
1357 if (chunk_len >
sizeof(buf))
1358 chunk_len =
sizeof(buf);
1365 while (total_wrote < ret) {
1366 wrote = write(fd, &buf[total_wrote],
1370 total_wrote += wrote;
1377 if (progress_callback)
1378 progress_callback(read, total_len);
1395 void (*progress_callback)(
int cur,
int tot))
1402 static int switchtec_fw_img_write_hdr_gen3(
int fd,
1408 memcpy(hdr.magic, ftr->magic,
sizeof(hdr.magic));
1409 hdr.image_len = ftr->image_len;
1411 hdr.load_addr = ftr->load_addr;
1412 hdr.version = ftr->version;
1413 hdr.header_crc = ftr->header_crc;
1414 hdr.image_crc = ftr->image_crc;
1416 if (hdr.type == SWITCHTEC_FW_PART_ID_G3_MAP1)
1417 hdr.type = SWITCHTEC_FW_PART_ID_G3_MAP0;
1418 else if (hdr.type == SWITCHTEC_FW_PART_ID_G3_IMG1)
1419 hdr.type = SWITCHTEC_FW_PART_ID_G3_IMG0;
1420 else if (hdr.type == SWITCHTEC_FW_PART_ID_G3_DAT1)
1421 hdr.type = SWITCHTEC_FW_PART_ID_G3_DAT0;
1423 return write(fd, &hdr,
sizeof(hdr));
1426 static int switchtec_fw_img_write_hdr_gen4(
int fd,
1432 ret = write(fd, hdr,
sizeof(*hdr));
1454 switch (info->
gen) {
1455 case SWITCHTEC_GEN3:
return switchtec_fw_img_write_hdr_gen3(fd, info);
1456 case SWITCHTEC_GEN4:
return switchtec_fw_img_write_hdr_gen4(fd, info);
1479 .subcmd = MRPC_FWDNLD_BOOT_RO,
1485 uint8_t reserved[3];
1495 ret =
switchtec_cmd(dev, MRPC_FWDNLD, &subcmd,
sizeof(subcmd),
1496 &result,
sizeof(result));
1498 if (ret == ERR_SUBCMD_INVALID) {
1506 return result.status;
1519 .subcmd = MRPC_FWDNLD_BOOT_RO,
1529 return switchtec_cmd(dev, MRPC_FWDNLD, &subcmd,
sizeof(subcmd),
char version[32]
Firmware/Config version.
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.
size_t part_addr
Address of the partition.
unsigned long image_crc
CRC checksum of the image.
enum switchtec_fw_type type
Image partition type.
Information about a firmware image or partition.
switchtec_boot_phase
Device boot phase.
int switchtec_fw_toggle_active_partition(struct switchtec_dev *dev, int toggle_bl2, int toggle_key, int toggle_fw, int toggle_cfg)
Toggle the active firmware partition for the main or configuration images.
int switchtec_fw_img_write_hdr(int fd, struct switchtec_fw_image_info *info)
Write the header for a Switchtec firmware image file.
unsigned long part_id
Image partition ID.
int switchtec_sn_ver_get(struct switchtec_dev *dev, struct switchtec_sn_ver_info *info)
Get serial number and security version.
size_t image_len
Length of the image.
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.
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.
void switchtec_fw_perror(const char *s, int ret)
Print an error string to stdout.
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_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_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.
enum switchtec_gen gen
Image generation.
switchtec_fw_ro
Flag which indicates if a partition is read-only or not.
void switchtec_fw_part_summary_free(struct switchtec_fw_part_summary *summary)
Free a firmware part summary data structure.
size_t part_body_offset
Partition image body offset.
int switchtec_fw_is_boot_ro(struct switchtec_dev *dev)
Check if the boot partition is marked as read-only.
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_file_info(int fd, struct switchtec_fw_image_info *info)
Retrieve information about a firmware image file.
int switchtec_fw_setup_redundancy(struct switchtec_dev *dev, enum switchtec_fw_redundancy redund, enum switchtec_fw_type type)
Set or clear the redundancy flag of a partition type.
switchtec_fw_dlstatus
Firmware update status.
const char * switchtec_fw_image_type(const struct switchtec_fw_image_info *info)
Return a string describing the type of a firmware image.
struct switchtec_fw_part_summary * switchtec_fw_part_summary(struct switchtec_dev *dev)
Return firmware summary information structure for the flash partitfons in the device.
size_t part_len
Length of the partition.
static int switchtec_is_gen3(struct switchtec_dev *dev)
Return whether a Switchtec device is a Gen 3 device.
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.
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.