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;
167static uint32_t get_fw_tx_id(
struct switchtec_dev *dev)
170 return MRPC_FW_TX_GEN5;
177 enum mrpc_bg_status *bgstatus)
179 uint32_t cmd = MRPC_FWDNLD;
180 uint32_t subcmd = MRPC_FWDNLD_GET_STATUS;
189 cmd = get_fw_tx_id(dev);
192 &result,
sizeof(result));
198 *status = result.dlstatus;
200 if (bgstatus != NULL)
201 *bgstatus = result.bgstatus;
206static int switchtec_fw_wait(
struct switchtec_dev *dev,
209 enum mrpc_bg_status bgstatus;
220 if (bgstatus == MRPC_BG_STAT_OFFSET)
221 return SWITCHTEC_DLSTAT_ERROR_OFFSET;
223 if (bgstatus == MRPC_BG_STAT_ERROR) {
224 if (*status != SWITCHTEC_DLSTAT_INPROGRESS &&
225 *status != SWITCHTEC_DLSTAT_COMPLETES &&
226 *status != SWITCHTEC_DLSTAT_SUCCESS_FIRM_ACT &&
227 *status != SWITCHTEC_DLSTAT_SUCCESS_DATA_ACT)
230 return SWITCHTEC_DLSTAT_ERROR_PROGRAM;
233 }
while (bgstatus == MRPC_BG_STAT_INPROGRESS);
238static int set_redundant(
struct switchtec_dev *dev,
int type,
int set)
241 char *part_types[] = {
252 uint8_t redundant_val;
256 cmd.subcmd = MRPC_FWDNLD_SET_RDNDNT;
257 cmd.redundant_val = set;
258 cmd.part_type = type;
260 printf(
"%s redundant flag \t(%s)\n", set ?
"Checking" :
"Un-checking",
262 ret =
switchtec_cmd(dev, MRPC_FWDNLD, &cmd,
sizeof(cmd), NULL, 0);
264 fprintf(stderr,
"Error: setting redudant flag \t(%s)\n",
269 printf(
"Success: set redundant flag \t(%s)\n",
282 int riot,
int bl2,
int cfg,
int fw,
287 ret += set_redundant(dev, SWITCHTEC_PART_TYPE_KEYMAN, set);
289 ret += set_redundant(dev, SWITCHTEC_PART_TYPE_RC, set);
291 ret += set_redundant(dev, SWITCHTEC_PART_TYPE_BL2, set);
293 ret += set_redundant(dev, SWITCHTEC_PART_TYPE_CFG, set);
295 ret += set_redundant(dev, SWITCHTEC_PART_TYPE_FW, set);
311 int toggle_bl2,
int toggle_key,
312 int toggle_fw,
int toggle_cfg,
323 uint8_t toggle_riotcore;
327 cmd_id = get_fw_tx_id(dev);
328 cmd.subcmd = MRPC_FW_TX_TOGGLE;
330 cmd_id = MRPC_FWDNLD;
331 cmd.subcmd = MRPC_FWDNLD_TOGGLE;
334 cmd.toggle_bl2 = !!toggle_bl2;
335 cmd.toggle_key = !!toggle_key;
336 cmd.toggle_fw = !!toggle_fw;
337 cmd.toggle_cfg = !!toggle_cfg;
339 cmd.toggle_riotcore = !!toggle_riotcore;
340 cmd_size =
sizeof(cmd);
342 cmd_size =
sizeof(cmd) - 1;
352 uint8_t dont_activate;
358 uint8_t data[MRPC_MAX_DATA_LEN -
sizeof(
struct cmd_fwdl_hdr)];
373 int dont_activate,
int force,
374 void (*progress_callback)(
int cur,
int tot))
377 enum mrpc_bg_status bgstatus;
378 ssize_t image_size, offset = 0;
381 uint32_t cmd_id = MRPC_FWDNLD;
384 cmd_id = get_fw_tx_id(dev);
386 image_size = lseek(img_fd, 0, SEEK_END);
389 lseek(img_fd, 0, SEEK_SET);
393 if (!force && status == SWITCHTEC_DLSTAT_INPROGRESS) {
398 if (bgstatus == MRPC_BG_STAT_INPROGRESS) {
404 cmd.hdr.subcmd = MRPC_FW_TX_FLASH;
406 cmd.hdr.subcmd = MRPC_FWDNLD_DOWNLOAD;
408 cmd.hdr.dont_activate = !!dont_activate;
409 cmd.hdr.img_length = htole32(image_size);
411 while (offset < image_size) {
412 ssize_t blklen = read(img_fd, &cmd.data,
415 if (blklen == -EAGAIN || blklen == -EWOULDBLOCK)
424 cmd.hdr.offset = htole32(offset);
425 cmd.hdr.blk_length = htole32(blklen);
433 ret = switchtec_fw_wait(dev, &status);
437 offset += le32toh(cmd.hdr.blk_length);
439 if (progress_callback)
440 progress_callback(offset, image_size);
444 if (status == SWITCHTEC_DLSTAT_COMPLETES)
447 if (status == SWITCHTEC_DLSTAT_SUCCESS_FIRM_ACT)
450 if (status == SWITCHTEC_DLSTAT_SUCCESS_DATA_ACT)
454 return SWITCHTEC_DLSTAT_HARDWARE_ERR;
466 uint8_t major = (version >> 24) & 0xff;
470 case 2:
return SWITCHTEC_GEN3;
473 case 5:
return SWITCHTEC_GEN4;
476 case 8:
return SWITCHTEC_GEN5;
477 default:
return SWITCHTEC_GEN_UNKNOWN;
493 int dont_activate,
int force,
494 void (*progress_callback)(
int cur,
int tot))
497 enum mrpc_bg_status bgstatus;
498 ssize_t image_size, offset = 0;
501 uint32_t cmd_id = MRPC_FWDNLD;
504 cmd_id = get_fw_tx_id(dev);
506 ret = fseek(fimg, 0, SEEK_END);
509 image_size = ftell(fimg);
512 ret = fseek(fimg, 0, SEEK_SET);
518 if (!force && status == SWITCHTEC_DLSTAT_INPROGRESS) {
523 if (bgstatus == MRPC_BG_STAT_INPROGRESS) {
529 cmd.hdr.subcmd = MRPC_FW_TX_FLASH;
531 cmd.hdr.subcmd = MRPC_FWDNLD_DOWNLOAD;
533 cmd.hdr.dont_activate = !!dont_activate;
534 cmd.hdr.img_length = htole32(image_size);
536 while (offset < image_size) {
537 ssize_t blklen = fread(&cmd.data, 1,
sizeof(cmd.data), fimg);
546 cmd.hdr.offset = htole32(offset);
547 cmd.hdr.blk_length = htole32(blklen);
555 ret = switchtec_fw_wait(dev, &status);
559 offset += le32toh(cmd.hdr.blk_length);
561 if (progress_callback)
562 progress_callback(offset, image_size);
565 if (status == SWITCHTEC_DLSTAT_COMPLETES)
568 if (status == SWITCHTEC_DLSTAT_SUCCESS_FIRM_ACT)
571 if (status == SWITCHTEC_DLSTAT_SUCCESS_DATA_ACT)
575 return SWITCHTEC_DLSTAT_HARDWARE_ERR;
598 case SWITCHTEC_DLSTAT_HEADER_INCORRECT:
599 msg =
"Header incorrect";
break;
600 case SWITCHTEC_DLSTAT_OFFSET_INCORRECT:
601 msg =
"Offset incorrect";
break;
602 case SWITCHTEC_DLSTAT_CRC_INCORRECT:
603 msg =
"CRC incorrect";
break;
604 case SWITCHTEC_DLSTAT_LENGTH_INCORRECT:
605 msg =
"Length incorrect";
break;
606 case SWITCHTEC_DLSTAT_HARDWARE_ERR:
607 msg =
"Hardware Error";
break;
608 case SWITCHTEC_DLSTAT_PACKAGE_TOO_SMALL:
609 msg =
"Package length less than 32 bytes";
break;
610 case SWITCHTEC_DLSTAT_SIG_MEM_ALLOC:
611 msg =
"Signature memory allocation failed";
break;
612 case SWITCHTEC_DLSTAT_SEEPROM:
613 msg =
"SEEPROM download failed";
break;
614 case SWITCHTEC_DLSTAT_READONLY_PARTITION:
615 msg =
"Programming a read-only partition";
break;
616 case SWITCHTEC_DLSTAT_DOWNLOAD_TIMEOUT:
617 msg =
"Download Timeout";
break;
618 case SWITCHTEC_DLSTAT_SEEPROM_TWI_NOT_ENABLED:
619 msg =
"SEEPROM or related TWI bus isn't enabled";
break;
620 case SWITCHTEC_DLSTAT_PROGRAM_RUNNING:
621 msg =
"Programming a running partition";
break;
622 case SWITCHTEC_DLSTAT_NOT_ALLOWED:
623 msg =
"Programming not allowed over this interface";
break;
624 case SWITCHTEC_DLSTAT_XML_MISMATCH_ACT:
625 msg =
"Activation failed due to XML version mismatch";
break;
626 case SWITCHTEC_DLSTAT_UNKNOWN_ACT:
627 msg =
"Activation failed due to unknown error";
break;
628 case SWITCHTEC_DLSTAT_ERROR_OFFSET:
629 msg =
"Data offset error during programming";
break;
630 case SWITCHTEC_DLSTAT_ERROR_PROGRAM:
631 msg =
"Failed to program to flash";
break;
633 case SWITCHTEC_DLSTAT_NO_FILE:
634 msg =
"No Image Transferred";
break;
636 fprintf(stderr,
"%s: Unknown Error (0x%x)\n", s, ret);
640 fprintf(stderr,
"%s: %s\n", s, msg);
643static enum switchtec_fw_type
646 switch ((
unsigned long)info->
part_id) {
647 case SWITCHTEC_FW_PART_ID_G3_BOOT:
return SWITCHTEC_FW_TYPE_BOOT;
648 case SWITCHTEC_FW_PART_ID_G3_MAP0:
return SWITCHTEC_FW_TYPE_MAP;
649 case SWITCHTEC_FW_PART_ID_G3_MAP1:
return SWITCHTEC_FW_TYPE_MAP;
650 case SWITCHTEC_FW_PART_ID_G3_IMG0:
return SWITCHTEC_FW_TYPE_IMG;
651 case SWITCHTEC_FW_PART_ID_G3_IMG1:
return SWITCHTEC_FW_TYPE_IMG;
652 case SWITCHTEC_FW_PART_ID_G3_DAT0:
return SWITCHTEC_FW_TYPE_CFG;
653 case SWITCHTEC_FW_PART_ID_G3_DAT1:
return SWITCHTEC_FW_TYPE_CFG;
654 case SWITCHTEC_FW_PART_ID_G3_NVLOG:
return SWITCHTEC_FW_TYPE_NVLOG;
655 case SWITCHTEC_FW_PART_ID_G3_SEEPROM:
return SWITCHTEC_FW_TYPE_SEEPROM;
658 case 0xa8000000:
return SWITCHTEC_FW_TYPE_BOOT;
659 case 0xa8020000:
return SWITCHTEC_FW_TYPE_MAP;
660 case 0xa8060000:
return SWITCHTEC_FW_TYPE_IMG;
661 case 0xa8210000:
return SWITCHTEC_FW_TYPE_CFG;
663 default:
return SWITCHTEC_FW_TYPE_UNKNOWN;
667static enum switchtec_fw_type
671 case SWITCHTEC_FW_PART_ID_G4_MAP0:
return SWITCHTEC_FW_TYPE_MAP;
672 case SWITCHTEC_FW_PART_ID_G4_MAP1:
return SWITCHTEC_FW_TYPE_MAP;
673 case SWITCHTEC_FW_PART_ID_G4_KEY0:
return SWITCHTEC_FW_TYPE_KEY;
674 case SWITCHTEC_FW_PART_ID_G4_KEY1:
return SWITCHTEC_FW_TYPE_KEY;
675 case SWITCHTEC_FW_PART_ID_G4_BL20:
return SWITCHTEC_FW_TYPE_BL2;
676 case SWITCHTEC_FW_PART_ID_G4_BL21:
return SWITCHTEC_FW_TYPE_BL2;
677 case SWITCHTEC_FW_PART_ID_G4_CFG0:
return SWITCHTEC_FW_TYPE_CFG;
678 case SWITCHTEC_FW_PART_ID_G4_CFG1:
return SWITCHTEC_FW_TYPE_CFG;
679 case SWITCHTEC_FW_PART_ID_G4_IMG0:
return SWITCHTEC_FW_TYPE_IMG;
680 case SWITCHTEC_FW_PART_ID_G4_IMG1:
return SWITCHTEC_FW_TYPE_IMG;
681 case SWITCHTEC_FW_PART_ID_G4_NVLOG:
return SWITCHTEC_FW_TYPE_NVLOG;
682 case SWITCHTEC_FW_PART_ID_G4_SEEPROM:
return SWITCHTEC_FW_TYPE_SEEPROM;
683 default:
return SWITCHTEC_FW_TYPE_UNKNOWN;
687static enum switchtec_fw_type
691 case SWITCHTEC_FW_PART_ID_G5_MAP0:
return SWITCHTEC_FW_TYPE_MAP;
692 case SWITCHTEC_FW_PART_ID_G5_MAP1:
return SWITCHTEC_FW_TYPE_MAP;
693 case SWITCHTEC_FW_PART_ID_G5_KEY0:
return SWITCHTEC_FW_TYPE_KEY;
694 case SWITCHTEC_FW_PART_ID_G5_KEY1:
return SWITCHTEC_FW_TYPE_KEY;
695 case SWITCHTEC_FW_PART_ID_G5_RIOT0:
return SWITCHTEC_FW_TYPE_RIOT;
696 case SWITCHTEC_FW_PART_ID_G5_RIOT1:
return SWITCHTEC_FW_TYPE_RIOT;
697 case SWITCHTEC_FW_PART_ID_G5_BL20:
return SWITCHTEC_FW_TYPE_BL2;
698 case SWITCHTEC_FW_PART_ID_G5_BL21:
return SWITCHTEC_FW_TYPE_BL2;
699 case SWITCHTEC_FW_PART_ID_G5_CFG0:
return SWITCHTEC_FW_TYPE_CFG;
700 case SWITCHTEC_FW_PART_ID_G5_CFG1:
return SWITCHTEC_FW_TYPE_CFG;
701 case SWITCHTEC_FW_PART_ID_G5_IMG0:
return SWITCHTEC_FW_TYPE_IMG;
702 case SWITCHTEC_FW_PART_ID_G5_IMG1:
return SWITCHTEC_FW_TYPE_IMG;
703 case SWITCHTEC_FW_PART_ID_G5_NVLOG:
return SWITCHTEC_FW_TYPE_NVLOG;
704 case SWITCHTEC_FW_PART_ID_G5_SEEPROM:
return SWITCHTEC_FW_TYPE_SEEPROM;
705 default:
return SWITCHTEC_FW_TYPE_UNKNOWN;
709static enum switchtec_fw_type
713 case SWITCHTEC_GEN3:
return switchtec_fw_id_to_type_gen3(info);
714 case SWITCHTEC_GEN4:
return switchtec_fw_id_to_type_gen4(info);
715 case SWITCHTEC_GEN5:
return switchtec_fw_id_to_type_gen5(info);
716 default:
return SWITCHTEC_FW_TYPE_UNKNOWN;
720static int switchtec_fw_file_info_gen3(
int fd,
726 ret = read(fd, &hdr,
sizeof(hdr));
727 lseek(fd, 0, SEEK_SET);
729 if (ret !=
sizeof(hdr))
732 if (strcmp(hdr.magic,
"PMC") != 0)
738 info->
gen = SWITCHTEC_GEN3;
740 info->
image_crc = le32toh(hdr.image_crc);
741 version_to_string(hdr.version, info->
version,
sizeof(info->
version));
742 info->
image_len = le32toh(hdr.image_len);
744 info->
type = switchtec_fw_id_to_type(info);
746 info->secure_version = 0;
747 info->signed_image = 0;
756static enum switchtec_fw_image_part_id_gen4 hdr_type2_id_gen4(uint32_t type)
759 case SWITCHTEC_FW_IMG_TYPE_MAP_GEN4:
760 return SWITCHTEC_FW_PART_ID_G4_MAP0;
762 case SWITCHTEC_FW_IMG_TYPE_KEYMAN_GEN4:
763 return SWITCHTEC_FW_PART_ID_G4_KEY0;
765 case SWITCHTEC_FW_IMG_TYPE_BL2_GEN4:
766 return SWITCHTEC_FW_PART_ID_G4_BL20;
768 case SWITCHTEC_FW_IMG_TYPE_CFG_GEN4:
769 return SWITCHTEC_FW_PART_ID_G4_CFG0;
771 case SWITCHTEC_FW_IMG_TYPE_IMG_GEN4:
772 return SWITCHTEC_FW_PART_ID_G4_IMG0;
774 case SWITCHTEC_FW_IMG_TYPE_NVLOG_GEN4:
775 return SWITCHTEC_FW_PART_ID_G4_NVLOG;
777 case SWITCHTEC_FW_IMG_TYPE_SEEPROM_GEN4:
778 return SWITCHTEC_FW_PART_ID_G4_SEEPROM;
785static enum switchtec_fw_image_part_id_gen5 hdr_type2_id_gen5(uint32_t type)
788 case SWITCHTEC_FW_IMG_TYPE_MAP_GEN5:
789 return SWITCHTEC_FW_PART_ID_G5_MAP0;
791 case SWITCHTEC_FW_IMG_TYPE_KEYMAN_GEN5:
792 return SWITCHTEC_FW_PART_ID_G5_KEY0;
794 case SWITCHTEC_FW_IMG_TYPE_RIOT_GEN5:
795 return SWITCHTEC_FW_PART_ID_G5_RIOT0;
797 case SWITCHTEC_FW_IMG_TYPE_BL2_GEN5:
798 return SWITCHTEC_FW_PART_ID_G5_BL20;
800 case SWITCHTEC_FW_IMG_TYPE_CFG_GEN5:
801 return SWITCHTEC_FW_PART_ID_G5_CFG0;
803 case SWITCHTEC_FW_IMG_TYPE_IMG_GEN5:
804 return SWITCHTEC_FW_PART_ID_G5_IMG0;
806 case SWITCHTEC_FW_IMG_TYPE_NVLOG_GEN5:
807 return SWITCHTEC_FW_PART_ID_G5_NVLOG;
809 case SWITCHTEC_FW_IMG_TYPE_SEEPROM_GEN5:
810 return SWITCHTEC_FW_PART_ID_G5_SEEPROM;
817static int switchtec_fw_file_info_gen45(
int fd,
822 uint8_t exp_zero[4] = {};
826 ret = read(fd, &hdr,
sizeof(hdr));
827 lseek(fd, 0, SEEK_SET);
829 if (ret !=
sizeof(hdr))
832 if (strncmp(hdr.magic,
"MSCC",
sizeof(hdr.magic)))
835 if (strncmp(hdr.sub_magic,
"_MD ",
sizeof(hdr.sub_magic)))
843 part_id = hdr_type2_id_gen5(le32toh(hdr.type));
845 part_id = hdr_type2_id_gen4(le32toh(hdr.type));
852 info->
image_crc = le32toh(hdr.image_crc);
853 version = le32toh(hdr.version);
855 info->
image_len = le32toh(hdr.image_len);
858 info->
type = switchtec_fw_id_to_type(info);
860 info->secure_version = le32toh(hdr.secure_version);
861 info->signed_image = !!memcmp(hdr.public_key_exponent, exp_zero, 4);
881 ret = read(fd, &magic,
sizeof(magic));
882 lseek(fd, 0, SEEK_SET);
884 if (ret !=
sizeof(magic)) {
889 if (!strncmp(magic,
"PMC",
sizeof(magic))) {
890 return switchtec_fw_file_info_gen3(fd, info);
891 }
else if (!strncmp(magic,
"MSCC",
sizeof(magic))) {
892 return switchtec_fw_file_info_gen45(fd, info);
923 if (!info.signed_image)
928 sn_info.ver_bl2 = 0xffffffff;
929 sn_info.ver_main = 0xffffffff;
930 sn_info.ver_km = 0xffffffff;
934 case SWITCHTEC_FW_TYPE_BL2:
935 if (info.secure_version > sn_info.ver_bl2)
939 case SWITCHTEC_FW_TYPE_IMG:
940 if (info.secure_version > sn_info.ver_main)
944 case SWITCHTEC_FW_TYPE_KEY:
945 if (info.secure_version > sn_info.ver_km)
963 switch (info->
type) {
964 case SWITCHTEC_FW_TYPE_BOOT:
return "BOOT";
965 case SWITCHTEC_FW_TYPE_MAP:
return "MAP";
966 case SWITCHTEC_FW_TYPE_IMG:
return "IMG";
967 case SWITCHTEC_FW_TYPE_CFG:
return "CFG";
968 case SWITCHTEC_FW_TYPE_KEY:
return "KEY";
969 case SWITCHTEC_FW_TYPE_RIOT:
return "RIOT";
970 case SWITCHTEC_FW_TYPE_BL2:
return "BL2";
971 case SWITCHTEC_FW_TYPE_NVLOG:
return "NVLOG";
972 case SWITCHTEC_FW_TYPE_SEEPROM:
return "SEEPROM";
973 default:
return "UNKNOWN";
977static int switchtec_fw_map_get_active(
struct switchtec_dev *dev,
980 uint32_t map0_update_index;
981 uint32_t map1_update_index;
985 sizeof(uint32_t), &map0_update_index);
990 sizeof(uint32_t), &map1_update_index);
995 if (map0_update_index > map1_update_index) {
996 if (info->
part_addr == SWITCHTEC_FLASH_MAP0_PART_START)
999 if (info->
part_addr == SWITCHTEC_FLASH_MAP1_PART_START)
1006static int switchtec_fw_info_metadata_gen3(
struct switchtec_dev *dev,
1013 if (inf->
part_id == SWITCHTEC_FW_PART_ID_G3_NVLOG)
1016 metadata = malloc(
sizeof(*metadata));
1026 if (strncmp(metadata->magic,
"PMC",
sizeof(metadata->magic)))
1029 version_to_string(metadata->version, inf->
version,
1034 inf->metadata = metadata;
1043static int switchtec_fw_part_info_gen3(
struct switchtec_dev *dev,
1051 case SWITCHTEC_FW_PART_ID_G3_BOOT:
1052 inf->
part_addr = SWITCHTEC_FLASH_BOOT_PART_START;
1053 inf->
part_len = SWITCHTEC_FLASH_PART_LEN;
1056 case SWITCHTEC_FW_PART_ID_G3_MAP0:
1057 inf->
part_addr = SWITCHTEC_FLASH_MAP0_PART_START;
1058 inf->
part_len = SWITCHTEC_FLASH_PART_LEN;
1059 ret = switchtec_fw_map_get_active(dev, inf);
1061 case SWITCHTEC_FW_PART_ID_G3_MAP1:
1062 inf->
part_addr = SWITCHTEC_FLASH_MAP1_PART_START;
1063 inf->
part_len = SWITCHTEC_FLASH_PART_LEN;
1064 ret = switchtec_fw_map_get_active(dev, inf);
1068 inf->read_only =
false;
1076 if (inf->
part_id == SWITCHTEC_FW_PART_ID_G3_NVLOG)
1079 return switchtec_fw_info_metadata_gen3(dev, inf);
1082static int switchtec_fw_info_metadata_gen4(
struct switchtec_dev *dev,
1090 .subcmd = MRPC_PART_INFO_GET_METADATA,
1095 if (inf->
part_id == SWITCHTEC_FW_PART_ID_G4_NVLOG)
1097 if (inf->
part_id == SWITCHTEC_FW_PART_ID_G4_SEEPROM)
1098 subcmd.subcmd = MRPC_PART_INFO_GET_SEEPROM;
1100 metadata = malloc(
sizeof(*metadata));
1104 ret =
switchtec_cmd(dev, MRPC_PART_INFO, &subcmd,
sizeof(subcmd),
1105 metadata,
sizeof(*metadata));
1109 if (strncmp(metadata->magic,
"MSCC",
sizeof(metadata->magic)))
1112 if (strncmp(metadata->sub_magic,
"_MD ",
sizeof(metadata->sub_magic)))
1115 version_to_string(le32toh(metadata->version), inf->
version,
1118 inf->
image_crc = le32toh(metadata->image_crc);
1119 inf->
image_len = le32toh(metadata->image_len);
1120 inf->metadata = metadata;
1129static int switchtec_fw_info_metadata_gen5(
struct switchtec_dev *dev,
1137 .subcmd = MRPC_PART_INFO_GET_METADATA_GEN5,
1142 if (inf->
part_id == SWITCHTEC_FW_PART_ID_G5_NVLOG)
1144 if (inf->
part_id == SWITCHTEC_FW_PART_ID_G5_SEEPROM)
1145 subcmd.subcmd = MRPC_PART_INFO_GET_SEEPROM;
1147 metadata = malloc(
sizeof(*metadata));
1151 ret =
switchtec_cmd(dev, MRPC_PART_INFO, &subcmd,
sizeof(subcmd),
1152 metadata,
sizeof(*metadata));
1156 if (strncmp(metadata->magic,
"MSCC",
sizeof(metadata->magic)))
1159 if (strncmp(metadata->sub_magic,
"_MD ",
sizeof(metadata->sub_magic)))
1162 version_to_string(le32toh(metadata->version), inf->
version,
1165 inf->
image_crc = le32toh(metadata->image_crc);
1166 inf->
image_len = le32toh(metadata->image_len);
1167 inf->metadata = metadata;
1177 uint32_t firmware_version;
1178 uint32_t flash_size;
1182 uint8_t running_bl2_flag;
1183 uint8_t running_cfg_flag;
1184 uint8_t running_img_flag;
1185 uint8_t running_key_flag;
1190 uint16_t image_version;
1193 uint32_t part_start;
1195 uint32_t part_offset;
1196 uint32_t part_size_dw;
1200 } map0, map1, keyman0, keyman1, bl20, bl21, cfg0, cfg1,
1201 img0, img1, nvlog, vendor[8];
1205 uint32_t firmware_version;
1206 uint32_t flash_size;
1210 uint8_t running_riot_flag;
1211 uint8_t running_bl2_flag;
1212 uint8_t running_cfg_flag;
1213 uint8_t running_img_flag;
1214 uint8_t running_key_flag;
1216 uint8_t key_redundant_flag;
1217 uint8_t riot_redundant_flag;
1218 uint8_t bl2_redundant_flag;
1219 uint8_t cfg_redundant_flag;
1220 uint8_t img_redundant_flag;
1223 struct switchtec_flash_part_info_gen4 map0, map1, keyman0, keyman1,
1224 riot0, riot1, bl20, bl21,
1225 cfg0, cfg1, img0, img1, nvlog,
1229static int switchtec_fw_part_info_gen4(
struct switchtec_dev *dev,
1233 struct switchtec_flash_part_info_gen4 *part_info;
1237 case SWITCHTEC_FW_PART_ID_G4_MAP0:
1238 part_info = &all->map0;
1240 case SWITCHTEC_FW_PART_ID_G4_MAP1:
1241 part_info = &all->map1;
1243 case SWITCHTEC_FW_PART_ID_G4_KEY0:
1244 part_info = &all->keyman0;
1246 case SWITCHTEC_FW_PART_ID_G4_KEY1:
1247 part_info = &all->keyman1;
1249 case SWITCHTEC_FW_PART_ID_G4_BL20:
1250 part_info = &all->bl20;
1252 case SWITCHTEC_FW_PART_ID_G4_BL21:
1253 part_info = &all->bl21;
1255 case SWITCHTEC_FW_PART_ID_G4_IMG0:
1256 part_info = &all->img0;
1258 case SWITCHTEC_FW_PART_ID_G4_IMG1:
1259 part_info = &all->img1;
1261 case SWITCHTEC_FW_PART_ID_G4_CFG0:
1262 part_info = &all->cfg0;
1264 case SWITCHTEC_FW_PART_ID_G4_CFG1:
1265 part_info = &all->cfg1;
1267 case SWITCHTEC_FW_PART_ID_G4_NVLOG:
1268 part_info = &all->nvlog;
1270 case SWITCHTEC_FW_PART_ID_G4_SEEPROM:
1278 ret = switchtec_fw_info_metadata_gen4(dev, inf);
1280 inf->running =
true;
1290 inf->
part_addr = le32toh(part_info->part_start);
1291 inf->
part_len = le32toh(part_info->part_size_dw) * 4;
1292 inf->active = part_info->active;
1293 inf->running = part_info->is_using;
1294 inf->read_only = part_info->read_only;
1295 inf->valid = part_info->valid;
1299 return switchtec_fw_info_metadata_gen4(dev, inf);
1302static int switchtec_fw_part_info_gen5(
struct switchtec_dev *dev,
1306 struct switchtec_flash_part_info_gen4 *part_info;
1310 case SWITCHTEC_FW_PART_ID_G5_MAP0:
1311 part_info = &all->map0;
1313 case SWITCHTEC_FW_PART_ID_G5_MAP1:
1314 part_info = &all->map1;
1316 case SWITCHTEC_FW_PART_ID_G5_RIOT0:
1317 inf->redundant = all->riot_redundant_flag;
1318 part_info = &all->riot0;
1320 case SWITCHTEC_FW_PART_ID_G5_RIOT1:
1321 inf->redundant = all->riot_redundant_flag;
1322 part_info = &all->riot1;
1324 case SWITCHTEC_FW_PART_ID_G5_KEY0:
1325 inf->redundant = all->key_redundant_flag;
1326 part_info = &all->keyman0;
1328 case SWITCHTEC_FW_PART_ID_G5_KEY1:
1329 inf->redundant = all->key_redundant_flag;
1330 part_info = &all->keyman1;
1332 case SWITCHTEC_FW_PART_ID_G5_BL20:
1333 inf->redundant = all->bl2_redundant_flag;
1334 part_info = &all->bl20;
1336 case SWITCHTEC_FW_PART_ID_G5_BL21:
1337 inf->redundant = all->bl2_redundant_flag;
1338 part_info = &all->bl21;
1340 case SWITCHTEC_FW_PART_ID_G5_IMG0:
1341 inf->redundant = all->img_redundant_flag;
1342 part_info = &all->img0;
1344 case SWITCHTEC_FW_PART_ID_G5_IMG1:
1345 inf->redundant = all->img_redundant_flag;
1346 part_info = &all->img1;
1348 case SWITCHTEC_FW_PART_ID_G5_CFG0:
1349 inf->redundant = all->cfg_redundant_flag;
1350 part_info = &all->cfg0;
1352 case SWITCHTEC_FW_PART_ID_G5_CFG1:
1353 inf->redundant = all->cfg_redundant_flag;
1354 part_info = &all->cfg1;
1356 case SWITCHTEC_FW_PART_ID_G5_NVLOG:
1357 part_info = &all->nvlog;
1359 case SWITCHTEC_FW_PART_ID_G5_SEEPROM:
1364 ret = switchtec_fw_info_metadata_gen5(dev, inf);
1366 inf->running =
true;
1376 inf->
part_addr = le32toh(part_info->part_start);
1377 inf->
part_len = le32toh(part_info->part_size_dw) * 4;
1378 inf->active = part_info->active;
1379 inf->running = part_info->is_using;
1380 inf->read_only = part_info->read_only;
1381 inf->valid = part_info->valid;
1385 return switchtec_fw_info_metadata_gen5(dev, inf);
1402 uint8_t subcmd = MRPC_PART_INFO_GET_ALL_INFO;
1406 if (info == NULL || nr_info == 0)
1409 if (dev->gen == SWITCHTEC_GEN4) {
1411 sizeof(subcmd), &all_info_gen4,
1412 sizeof(all_info_gen4));
1415 all_info_gen4.firmware_version =
1416 le32toh(all_info_gen4.firmware_version);
1417 all_info_gen4.flash_size = le32toh(all_info_gen4.flash_size);
1418 all_info_gen4.device_id = le16toh(all_info_gen4.device_id);
1419 }
else if (dev->gen == SWITCHTEC_GEN5) {
1420 subcmd = MRPC_PART_INFO_GET_ALL_INFO_GEN5;
1422 sizeof(subcmd), &all_info_gen5,
1423 sizeof(all_info_gen5));
1426 all_info_gen5.firmware_version =
1427 le32toh(all_info_gen5.firmware_version);
1428 all_info_gen5.flash_size = le32toh(all_info_gen5.flash_size);
1429 all_info_gen5.device_id = le16toh(all_info_gen5.device_id);
1432 for (i = 0; i < nr_info; i++) {
1436 inf->
gen = dev->gen;
1437 inf->
type = switchtec_fw_id_to_type(inf);
1438 inf->active =
false;
1439 inf->running =
false;
1442 switch (info->
gen) {
1443 case SWITCHTEC_GEN3:
1444 ret = switchtec_fw_part_info_gen3(dev, inf);
1446 case SWITCHTEC_GEN4:
1447 ret = switchtec_fw_part_info_gen4(dev, inf,
1450 case SWITCHTEC_GEN5:
1451 ret = switchtec_fw_part_info_gen5(dev, inf,
1465 inf->metadata = NULL;
1472int switchtec_get_device_id_bl2(
struct switchtec_dev *dev,
1473 unsigned short *device_id)
1476 uint8_t subcmd = MRPC_PART_INFO_GET_ALL_INFO;
1480 if (dev->gen != SWITCHTEC_GEN_UNKNOWN)
1484 sizeof(subcmd), &all_info,
1487 *device_id = le16toh(all_info.device_id);
1488 }
else if (ret == ERR_SUBCMD_INVALID) {
1489 subcmd = MRPC_PART_INFO_GET_ALL_INFO_GEN5;
1491 sizeof(subcmd), &all_info_gen5,
1492 sizeof(all_info_gen5));
1494 *device_id = le16toh(all_info_gen5.device_id);
1500static long multicfg_subcmd(
struct switchtec_dev *dev, uint32_t subcmd,
1506 subcmd |= index << 8;
1507 subcmd = htole32(subcmd);
1509 ret =
switchtec_cmd(dev, MRPC_MULTI_CFG, &subcmd,
sizeof(subcmd),
1510 &result,
sizeof(result));
1517static int get_multicfg(
struct switchtec_dev *dev,
1524 ret = multicfg_subcmd(dev, MRPC_MULTI_CFG_SUPPORTED, 0);
1533 ret = multicfg_subcmd(dev, MRPC_MULTI_CFG_COUNT, 0);
1540 for (i = 0; i < *nr_mult; i++) {
1541 info[i].
part_addr = multicfg_subcmd(dev,
1542 MRPC_MULTI_CFG_START_ADDR,
1544 info[i].
part_len = multicfg_subcmd(dev,
1545 MRPC_MULTI_CFG_LENGTH, i);
1546 strcpy(info[i].version,
"");
1551 ret = multicfg_subcmd(dev, MRPC_MULTI_CFG_ACTIVE, 0);
1556 info[ret].active = 1;
1561static const enum switchtec_fw_image_part_id_gen3
1562switchtec_fw_partitions_gen3[] = {
1563 SWITCHTEC_FW_PART_ID_G3_BOOT,
1564 SWITCHTEC_FW_PART_ID_G3_MAP0,
1565 SWITCHTEC_FW_PART_ID_G3_MAP1,
1566 SWITCHTEC_FW_PART_ID_G3_IMG0,
1567 SWITCHTEC_FW_PART_ID_G3_DAT0,
1568 SWITCHTEC_FW_PART_ID_G3_DAT1,
1569 SWITCHTEC_FW_PART_ID_G3_NVLOG,
1570 SWITCHTEC_FW_PART_ID_G3_IMG1,
1573static const enum switchtec_fw_image_part_id_gen4
1574switchtec_fw_partitions_gen4[] = {
1575 SWITCHTEC_FW_PART_ID_G4_MAP0,
1576 SWITCHTEC_FW_PART_ID_G4_MAP1,
1577 SWITCHTEC_FW_PART_ID_G4_KEY0,
1578 SWITCHTEC_FW_PART_ID_G4_KEY1,
1579 SWITCHTEC_FW_PART_ID_G4_BL20,
1580 SWITCHTEC_FW_PART_ID_G4_BL21,
1581 SWITCHTEC_FW_PART_ID_G4_CFG0,
1582 SWITCHTEC_FW_PART_ID_G4_CFG1,
1583 SWITCHTEC_FW_PART_ID_G4_IMG0,
1584 SWITCHTEC_FW_PART_ID_G4_IMG1,
1585 SWITCHTEC_FW_PART_ID_G4_NVLOG,
1586 SWITCHTEC_FW_PART_ID_G4_SEEPROM,
1589static const enum switchtec_fw_image_part_id_gen5
1590switchtec_fw_partitions_gen5[] = {
1591 SWITCHTEC_FW_PART_ID_G5_MAP0,
1592 SWITCHTEC_FW_PART_ID_G5_MAP1,
1593 SWITCHTEC_FW_PART_ID_G5_KEY0,
1594 SWITCHTEC_FW_PART_ID_G5_KEY1,
1595 SWITCHTEC_FW_PART_ID_G5_RIOT0,
1596 SWITCHTEC_FW_PART_ID_G5_RIOT1,
1597 SWITCHTEC_FW_PART_ID_G5_BL20,
1598 SWITCHTEC_FW_PART_ID_G5_BL21,
1599 SWITCHTEC_FW_PART_ID_G5_CFG0,
1600 SWITCHTEC_FW_PART_ID_G5_CFG1,
1601 SWITCHTEC_FW_PART_ID_G5_IMG0,
1602 SWITCHTEC_FW_PART_ID_G5_IMG1,
1603 SWITCHTEC_FW_PART_ID_G5_NVLOG,
1604 SWITCHTEC_FW_PART_ID_G5_SEEPROM,
1607static struct switchtec_fw_part_type *
1611 switch (info->
type) {
1612 case SWITCHTEC_FW_TYPE_BOOT:
return &summary->boot;
1613 case SWITCHTEC_FW_TYPE_MAP:
return &summary->map;
1614 case SWITCHTEC_FW_TYPE_IMG:
return &summary->img;
1615 case SWITCHTEC_FW_TYPE_CFG:
return &summary->cfg;
1616 case SWITCHTEC_FW_TYPE_NVLOG:
return &summary->nvlog;
1617 case SWITCHTEC_FW_TYPE_SEEPROM:
return &summary->seeprom;
1618 case SWITCHTEC_FW_TYPE_KEY:
return &summary->key;
1619 case SWITCHTEC_FW_TYPE_BL2:
return &summary->bl2;
1620 case SWITCHTEC_FW_TYPE_RIOT:
return &summary->riot;
1621 default:
return NULL;
1638 struct switchtec_fw_part_type *type;
1639 int nr_info, nr_mcfg = 16;
1644 case SWITCHTEC_GEN3:
1645 nr_info = ARRAY_SIZE(switchtec_fw_partitions_gen3);
1647 case SWITCHTEC_GEN4:
1648 nr_info = ARRAY_SIZE(switchtec_fw_partitions_gen4);
1650 case SWITCHTEC_GEN5:
1651 nr_info = ARRAY_SIZE(switchtec_fw_partitions_gen5);
1658 st_sz =
sizeof(*summary) +
sizeof(*summary->all) * (nr_info + nr_mcfg);
1660 summary = malloc(st_sz);
1664 memset(summary, 0, st_sz);
1665 summary->nr_info = nr_info;
1668 case SWITCHTEC_GEN3:
1669 for (i = 0; i < nr_info; i++)
1671 switchtec_fw_partitions_gen3[i];
1673 case SWITCHTEC_GEN4:
1674 for (i = 0; i < nr_info; i++)
1676 switchtec_fw_partitions_gen4[i];
1678 case SWITCHTEC_GEN5:
1679 for (i = 0; i < nr_info; i++)
1681 switchtec_fw_partitions_gen5[i];
1690 if (ret != nr_info) {
1695 ret = get_multicfg(dev, &summary->all[nr_info], &nr_mcfg);
1701 for (i = 0; i < nr_info; i++) {
1702 type = switchtec_fw_type_ptr(summary, &summary->all[i]);
1707 if (summary->all[i].active)
1708 type->active = &summary->all[i];
1710 type->inactive = &summary->all[i];
1713 infp = &summary->mult_cfg;
1714 for (; i < nr_info + nr_mcfg; i++) {
1715 *infp = &summary->all[i];
1716 infp = &summary->all[i].next;
1730 for (i = 0; i < summary->nr_info; i++)
1731 free(summary->all[i].metadata);
1745 size_t len,
void *buf)
1752 unsigned char *cbuf = buf;
1756 size_t chunk_len = len;
1757 if (chunk_len > MRPC_MAX_DATA_LEN-8)
1758 chunk_len = MRPC_MAX_DATA_LEN-8;
1760 cmd.addr = htole32(addr);
1761 cmd.length = htole32(chunk_len);
1789 unsigned long addr,
size_t len,
1790 void (*progress_callback)(
int cur,
int tot))
1793 unsigned char buf[(MRPC_MAX_DATA_LEN-8)*4];
1795 size_t total_len = len;
1800 size_t chunk_len = len;
1801 if (chunk_len >
sizeof(buf))
1802 chunk_len =
sizeof(buf);
1809 while (total_wrote < ret) {
1810 wrote = write(fd, &buf[total_wrote],
1814 total_wrote += wrote;
1821 if (progress_callback)
1822 progress_callback(read, total_len);
1839 void (*progress_callback)(
int cur,
int tot))
1846static int switchtec_fw_img_write_hdr_gen3(
int fd,
1852 memcpy(hdr.magic, ftr->magic,
sizeof(hdr.magic));
1853 hdr.image_len = ftr->image_len;
1855 hdr.load_addr = ftr->load_addr;
1856 hdr.version = ftr->version;
1857 hdr.header_crc = ftr->header_crc;
1858 hdr.image_crc = ftr->image_crc;
1860 if (hdr.type == SWITCHTEC_FW_PART_ID_G3_MAP1)
1861 hdr.type = SWITCHTEC_FW_PART_ID_G3_MAP0;
1862 else if (hdr.type == SWITCHTEC_FW_PART_ID_G3_IMG1)
1863 hdr.type = SWITCHTEC_FW_PART_ID_G3_IMG0;
1864 else if (hdr.type == SWITCHTEC_FW_PART_ID_G3_DAT1)
1865 hdr.type = SWITCHTEC_FW_PART_ID_G3_DAT0;
1867 return write(fd, &hdr,
sizeof(hdr));
1870static int switchtec_fw_img_write_hdr_gen4(
int fd,
1876 ret = write(fd, hdr,
sizeof(*hdr));
1898 switch (info->
gen) {
1899 case SWITCHTEC_GEN3:
return switchtec_fw_img_write_hdr_gen3(fd, info);
1900 case SWITCHTEC_GEN4:
1901 case SWITCHTEC_GEN5:
return switchtec_fw_img_write_hdr_gen4(fd, info);
1924 .subcmd = MRPC_FWDNLD_BOOT_RO,
1930 uint8_t reserved[3];
1940 ret =
switchtec_cmd(dev, MRPC_FWDNLD, &subcmd,
sizeof(subcmd),
1941 &result,
sizeof(result));
1943 if (ret == ERR_SUBCMD_INVALID) {
1951 return result.status;
1964 .subcmd = MRPC_FWDNLD_BOOT_RO,
1974 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_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.
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.
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.
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.
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.
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.