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,
80 uint32_t secure_version;
82 uint32_t metadata_len;
94 uint8_t public_key_modulus[512];
95 uint8_t public_key_exponent[4];
97 uint8_t uart_rate : 6;
98 uint8_t uart_parity : 2;
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;
165 if (bgstatus == MRPC_BG_STAT_OFFSET)
166 return SWITCHTEC_DLSTAT_ERROR_OFFSET;
168 if (bgstatus == MRPC_BG_STAT_ERROR) {
169 if (*status != SWITCHTEC_DLSTAT_INPROGRESS &&
170 *status != SWITCHTEC_DLSTAT_COMPLETES &&
171 *status != SWITCHTEC_DLSTAT_SUCCESS_FIRM_ACT &&
172 *status != SWITCHTEC_DLSTAT_SUCCESS_DATA_ACT)
175 return SWITCHTEC_DLSTAT_ERROR_PROGRAM;
178 }
while (bgstatus == MRPC_BG_STAT_INPROGRESS);
194 int toggle_bl2,
int toggle_key,
195 int toggle_fw,
int toggle_cfg)
208 cmd.subcmd = MRPC_FW_TX_TOGGLE;
210 cmd_id = MRPC_FWDNLD;
211 cmd.subcmd = MRPC_FWDNLD_TOGGLE;
214 cmd.toggle_bl2 = !!toggle_bl2;
215 cmd.toggle_key = !!toggle_key;
216 cmd.toggle_fw = !!toggle_fw;
217 cmd.toggle_cfg = !!toggle_cfg;
226 uint8_t dont_activate;
232 uint8_t data[MRPC_MAX_DATA_LEN -
sizeof(
struct cmd_fwdl_hdr)];
247 int dont_activate,
int force,
248 void (*progress_callback)(
int cur,
int tot))
251 enum mrpc_bg_status bgstatus;
252 ssize_t image_size, offset = 0;
255 uint32_t cmd_id = MRPC_FWDNLD;
260 image_size = lseek(img_fd, 0, SEEK_END);
263 lseek(img_fd, 0, SEEK_SET);
267 if (!force && status == SWITCHTEC_DLSTAT_INPROGRESS) {
272 if (bgstatus == MRPC_BG_STAT_INPROGRESS) {
278 cmd.hdr.subcmd = MRPC_FW_TX_FLASH;
280 cmd.hdr.subcmd = MRPC_FWDNLD_DOWNLOAD;
282 cmd.hdr.dont_activate = !!dont_activate;
283 cmd.hdr.img_length = htole32(image_size);
285 while (offset < image_size) {
286 ssize_t blklen = read(img_fd, &cmd.data,
289 if (blklen == -EAGAIN || blklen == -EWOULDBLOCK)
298 cmd.hdr.offset = htole32(offset);
299 cmd.hdr.blk_length = htole32(blklen);
307 ret = switchtec_fw_wait(dev, &status);
311 offset += le32toh(cmd.hdr.blk_length);
313 if (progress_callback)
314 progress_callback(offset, image_size);
318 if (status == SWITCHTEC_DLSTAT_COMPLETES)
321 if (status == SWITCHTEC_DLSTAT_SUCCESS_FIRM_ACT)
324 if (status == SWITCHTEC_DLSTAT_SUCCESS_DATA_ACT)
328 return SWITCHTEC_DLSTAT_HARDWARE_ERR;
340 uint8_t major = (version >> 24) & 0xff;
344 case 2:
return SWITCHTEC_GEN3;
347 case 5:
return SWITCHTEC_GEN4;
350 case 8:
return SWITCHTEC_GEN5;
351 default:
return SWITCHTEC_GEN_UNKNOWN;
367 int dont_activate,
int force,
368 void (*progress_callback)(
int cur,
int tot))
371 enum mrpc_bg_status bgstatus;
372 ssize_t image_size, offset = 0;
375 uint32_t cmd_id = MRPC_FWDNLD;
380 ret = fseek(fimg, 0, SEEK_END);
383 image_size = ftell(fimg);
386 ret = fseek(fimg, 0, SEEK_SET);
392 if (!force && status == SWITCHTEC_DLSTAT_INPROGRESS) {
397 if (bgstatus == MRPC_BG_STAT_INPROGRESS) {
403 cmd.hdr.subcmd = MRPC_FW_TX_FLASH;
405 cmd.hdr.subcmd = MRPC_FWDNLD_DOWNLOAD;
407 cmd.hdr.dont_activate = !!dont_activate;
408 cmd.hdr.img_length = htole32(image_size);
410 while (offset < image_size) {
411 ssize_t blklen = fread(&cmd.data, 1,
sizeof(cmd.data), fimg);
420 cmd.hdr.offset = htole32(offset);
421 cmd.hdr.blk_length = htole32(blklen);
429 ret = switchtec_fw_wait(dev, &status);
433 offset += le32toh(cmd.hdr.blk_length);
435 if (progress_callback)
436 progress_callback(offset, image_size);
439 if (status == SWITCHTEC_DLSTAT_COMPLETES)
442 if (status == SWITCHTEC_DLSTAT_SUCCESS_FIRM_ACT)
445 if (status == SWITCHTEC_DLSTAT_SUCCESS_DATA_ACT)
449 return SWITCHTEC_DLSTAT_HARDWARE_ERR;
472 case SWITCHTEC_DLSTAT_HEADER_INCORRECT:
473 msg =
"Header incorrect";
break;
474 case SWITCHTEC_DLSTAT_OFFSET_INCORRECT:
475 msg =
"Offset incorrect";
break;
476 case SWITCHTEC_DLSTAT_CRC_INCORRECT:
477 msg =
"CRC incorrect";
break;
478 case SWITCHTEC_DLSTAT_LENGTH_INCORRECT:
479 msg =
"Length incorrect";
break;
480 case SWITCHTEC_DLSTAT_HARDWARE_ERR:
481 msg =
"Hardware Error";
break;
482 case SWITCHTEC_DLSTAT_PACKAGE_TOO_SMALL:
483 msg =
"Package length less than 32 bytes";
break;
484 case SWITCHTEC_DLSTAT_SIG_MEM_ALLOC:
485 msg =
"Signature memory allocation failed";
break;
486 case SWITCHTEC_DLSTAT_SEEPROM:
487 msg =
"SEEPROM download failed";
break;
488 case SWITCHTEC_DLSTAT_READONLY_PARTITION:
489 msg =
"Programming a read-only partition";
break;
490 case SWITCHTEC_DLSTAT_DOWNLOAD_TIMEOUT:
491 msg =
"Download Timeout";
break;
492 case SWITCHTEC_DLSTAT_SEEPROM_TWI_NOT_ENABLED:
493 msg =
"SEEPROM or related TWI bus isn't enabled";
break;
494 case SWITCHTEC_DLSTAT_PROGRAM_RUNNING:
495 msg =
"Programming a running partition";
break;
496 case SWITCHTEC_DLSTAT_NOT_ALLOWED:
497 msg =
"Programming not allowed over this interface";
break;
498 case SWITCHTEC_DLSTAT_XML_MISMATCH_ACT:
499 msg =
"Activation failed due to XML version mismatch";
break;
500 case SWITCHTEC_DLSTAT_UNKNOWN_ACT:
501 msg =
"Activation failed due to unknown error";
break;
502 case SWITCHTEC_DLSTAT_ERROR_OFFSET:
503 msg =
"Data offset error during programming";
break;
504 case SWITCHTEC_DLSTAT_ERROR_PROGRAM:
505 msg =
"Failed to program to flash";
break;
506 case SWITCHTEC_DLSTAT_METADATA_LEN_INCORRECT:
507 msg =
"Image transfer metadata length incorrect";
break;
508 case SWITCHTEC_DLSTAT_FLM_NOT_INIT:
509 msg =
"MRPC command not Supported as flash is not initialized";
513 case SWITCHTEC_DLSTAT_NO_FILE:
514 msg =
"No Image Transferred";
break;
516 fprintf(stderr,
"%s: Unknown Error (0x%x)\n", s, ret);
520 fprintf(stderr,
"%s: %s\n", s, msg);
523 static enum switchtec_fw_type
526 switch ((
unsigned long)info->
part_id) {
527 case SWITCHTEC_FW_PART_ID_G3_BOOT:
return SWITCHTEC_FW_TYPE_BOOT;
528 case SWITCHTEC_FW_PART_ID_G3_MAP0:
return SWITCHTEC_FW_TYPE_MAP;
529 case SWITCHTEC_FW_PART_ID_G3_MAP1:
return SWITCHTEC_FW_TYPE_MAP;
530 case SWITCHTEC_FW_PART_ID_G3_IMG0:
return SWITCHTEC_FW_TYPE_IMG;
531 case SWITCHTEC_FW_PART_ID_G3_IMG1:
return SWITCHTEC_FW_TYPE_IMG;
532 case SWITCHTEC_FW_PART_ID_G3_DAT0:
return SWITCHTEC_FW_TYPE_CFG;
533 case SWITCHTEC_FW_PART_ID_G3_DAT1:
return SWITCHTEC_FW_TYPE_CFG;
534 case SWITCHTEC_FW_PART_ID_G3_NVLOG:
return SWITCHTEC_FW_TYPE_NVLOG;
535 case SWITCHTEC_FW_PART_ID_G3_SEEPROM:
return SWITCHTEC_FW_TYPE_SEEPROM;
538 case 0xa8000000:
return SWITCHTEC_FW_TYPE_BOOT;
539 case 0xa8020000:
return SWITCHTEC_FW_TYPE_MAP;
540 case 0xa8060000:
return SWITCHTEC_FW_TYPE_IMG;
541 case 0xa8210000:
return SWITCHTEC_FW_TYPE_CFG;
543 default:
return SWITCHTEC_FW_TYPE_UNKNOWN;
547 static enum switchtec_fw_type
551 case SWITCHTEC_FW_PART_ID_G4_MAP0:
return SWITCHTEC_FW_TYPE_MAP;
552 case SWITCHTEC_FW_PART_ID_G4_MAP1:
return SWITCHTEC_FW_TYPE_MAP;
553 case SWITCHTEC_FW_PART_ID_G4_KEY0:
return SWITCHTEC_FW_TYPE_KEY;
554 case SWITCHTEC_FW_PART_ID_G4_KEY1:
return SWITCHTEC_FW_TYPE_KEY;
555 case SWITCHTEC_FW_PART_ID_G4_BL20:
return SWITCHTEC_FW_TYPE_BL2;
556 case SWITCHTEC_FW_PART_ID_G4_BL21:
return SWITCHTEC_FW_TYPE_BL2;
557 case SWITCHTEC_FW_PART_ID_G4_CFG0:
return SWITCHTEC_FW_TYPE_CFG;
558 case SWITCHTEC_FW_PART_ID_G4_CFG1:
return SWITCHTEC_FW_TYPE_CFG;
559 case SWITCHTEC_FW_PART_ID_G4_IMG0:
return SWITCHTEC_FW_TYPE_IMG;
560 case SWITCHTEC_FW_PART_ID_G4_IMG1:
return SWITCHTEC_FW_TYPE_IMG;
561 case SWITCHTEC_FW_PART_ID_G4_NVLOG:
return SWITCHTEC_FW_TYPE_NVLOG;
562 case SWITCHTEC_FW_PART_ID_G4_SEEPROM:
return SWITCHTEC_FW_TYPE_SEEPROM;
563 default:
return SWITCHTEC_FW_TYPE_UNKNOWN;
567 static enum switchtec_fw_type
571 case SWITCHTEC_GEN3:
return switchtec_fw_id_to_type_gen3(info);
573 case SWITCHTEC_GEN5:
return switchtec_fw_id_to_type_gen4(info);
574 default:
return SWITCHTEC_FW_TYPE_UNKNOWN;
578 static int switchtec_fw_file_info_gen3(
int fd,
584 ret = read(fd, &hdr,
sizeof(hdr));
585 lseek(fd, 0, SEEK_SET);
587 if (ret !=
sizeof(hdr))
590 if (strcmp(hdr.magic,
"PMC") != 0)
596 info->
gen = SWITCHTEC_GEN3;
598 info->
image_crc = le32toh(hdr.image_crc);
599 version_to_string(hdr.version, info->
version,
sizeof(info->
version));
600 info->
image_len = le32toh(hdr.image_len);
602 info->
type = switchtec_fw_id_to_type(info);
604 info->secure_version = 0;
605 info->signed_image = 0;
614 static int switchtec_fw_file_info_gen4(
int fd,
619 uint8_t exp_zero[4] = {};
622 ret = read(fd, &hdr,
sizeof(hdr));
623 lseek(fd, 0, SEEK_SET);
625 if (ret !=
sizeof(hdr))
628 if (strncmp(hdr.magic,
"MSCC",
sizeof(hdr.magic)))
631 if (strncmp(hdr.sub_magic,
"_MD ",
sizeof(hdr.sub_magic)))
637 switch (le32toh(hdr.type)) {
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 = le32toh(hdr.version);
666 info->
image_len = le32toh(hdr.image_len);
669 info->
type = switchtec_fw_id_to_type(info);
671 info->secure_version = le32toh(hdr.secure_version);
672 info->signed_image = !!memcmp(hdr.public_key_exponent, exp_zero, 4);
692 ret = read(fd, &magic,
sizeof(magic));
693 lseek(fd, 0, SEEK_SET);
695 if (ret !=
sizeof(magic)) {
700 if (!strncmp(magic,
"PMC",
sizeof(magic))) {
701 return switchtec_fw_file_info_gen3(fd, info);
702 }
else if (!strncmp(magic,
"MSCC",
sizeof(magic))) {
703 return switchtec_fw_file_info_gen4(fd, info);
734 if (!info.signed_image)
739 sn_info.ver_bl2 = 0xffffffff;
740 sn_info.ver_main = 0xffffffff;
741 sn_info.ver_km = 0xffffffff;
745 case SWITCHTEC_FW_TYPE_BL2:
746 if (info.secure_version > sn_info.ver_bl2)
750 case SWITCHTEC_FW_TYPE_IMG:
751 if (info.secure_version > sn_info.ver_main)
755 case SWITCHTEC_FW_TYPE_KEY:
756 if (info.secure_version > sn_info.ver_km)
774 switch (info->
type) {
775 case SWITCHTEC_FW_TYPE_BOOT:
return "BOOT";
776 case SWITCHTEC_FW_TYPE_MAP:
return "MAP";
777 case SWITCHTEC_FW_TYPE_IMG:
return "IMG";
778 case SWITCHTEC_FW_TYPE_CFG:
return "CFG";
779 case SWITCHTEC_FW_TYPE_KEY:
return "KEY";
780 case SWITCHTEC_FW_TYPE_BL2:
return "BL2";
781 case SWITCHTEC_FW_TYPE_NVLOG:
return "NVLOG";
782 case SWITCHTEC_FW_TYPE_SEEPROM:
return "SEEPROM";
783 default:
return "UNKNOWN";
787 static int switchtec_fw_map_get_active(
struct switchtec_dev *dev,
790 uint32_t map0_update_index;
791 uint32_t map1_update_index;
795 sizeof(uint32_t), &map0_update_index);
800 sizeof(uint32_t), &map1_update_index);
805 if (map0_update_index > map1_update_index) {
806 if (info->
part_addr == SWITCHTEC_FLASH_MAP0_PART_START)
809 if (info->
part_addr == SWITCHTEC_FLASH_MAP1_PART_START)
816 static int switchtec_fw_info_metadata_gen3(
struct switchtec_dev *dev,
823 if (inf->
part_id == SWITCHTEC_FW_PART_ID_G3_NVLOG)
826 metadata = malloc(
sizeof(*metadata));
836 if (strncmp(metadata->magic,
"PMC",
sizeof(metadata->magic)))
839 version_to_string(metadata->version, inf->
version,
844 inf->metadata = metadata;
853 static int switchtec_fw_part_info_gen3(
struct switchtec_dev *dev,
861 case SWITCHTEC_FW_PART_ID_G3_BOOT:
862 inf->
part_addr = SWITCHTEC_FLASH_BOOT_PART_START;
863 inf->
part_len = SWITCHTEC_FLASH_PART_LEN;
866 case SWITCHTEC_FW_PART_ID_G3_MAP0:
867 inf->
part_addr = SWITCHTEC_FLASH_MAP0_PART_START;
868 inf->
part_len = SWITCHTEC_FLASH_PART_LEN;
869 ret = switchtec_fw_map_get_active(dev, inf);
871 case SWITCHTEC_FW_PART_ID_G3_MAP1:
872 inf->
part_addr = SWITCHTEC_FLASH_MAP1_PART_START;
873 inf->
part_len = SWITCHTEC_FLASH_PART_LEN;
874 ret = switchtec_fw_map_get_active(dev, inf);
878 inf->read_only =
false;
886 if (inf->
part_id == SWITCHTEC_FW_PART_ID_G3_NVLOG)
889 return switchtec_fw_info_metadata_gen3(dev, inf);
892 static int switchtec_fw_info_metadata_gen4(
struct switchtec_dev *dev,
900 .subcmd = MRPC_PART_INFO_GET_METADATA,
905 if (inf->
part_id == SWITCHTEC_FW_PART_ID_G4_NVLOG)
907 if (inf->
part_id == SWITCHTEC_FW_PART_ID_G4_SEEPROM)
908 subcmd.subcmd = MRPC_PART_INFO_GET_SEEPROM;
910 metadata = malloc(
sizeof(*metadata));
914 ret =
switchtec_cmd(dev, MRPC_PART_INFO, &subcmd,
sizeof(subcmd),
915 metadata,
sizeof(*metadata));
919 if (strncmp(metadata->magic,
"MSCC",
sizeof(metadata->magic)))
922 if (strncmp(metadata->sub_magic,
"_MD ",
sizeof(metadata->sub_magic)))
925 version_to_string(le32toh(metadata->version), inf->
version,
928 inf->
image_crc = le32toh(metadata->image_crc);
929 inf->
image_len = le32toh(metadata->image_len);
930 inf->metadata = metadata;
940 uint32_t firmware_version;
945 uint8_t running_bl2_flag;
946 uint8_t running_cfg_flag;
947 uint8_t running_img_flag;
948 uint8_t running_key_flag;
953 uint16_t image_version;
958 uint32_t part_offset;
959 uint32_t part_size_dw;
963 } map0, map1, keyman0, keyman1, bl20, bl21, cfg0, cfg1,
964 img0, img1, nvlog, vendor[8];
967 static int switchtec_fw_part_info_gen4(
struct switchtec_dev *dev,
971 struct switchtec_flash_part_info_gen4 *part_info;
975 case SWITCHTEC_FW_PART_ID_G4_MAP0:
976 part_info = &all->map0;
978 case SWITCHTEC_FW_PART_ID_G4_MAP1:
979 part_info = &all->map1;
981 case SWITCHTEC_FW_PART_ID_G4_KEY0:
982 part_info = &all->keyman0;
984 case SWITCHTEC_FW_PART_ID_G4_KEY1:
985 part_info = &all->keyman1;
987 case SWITCHTEC_FW_PART_ID_G4_BL20:
988 part_info = &all->bl20;
990 case SWITCHTEC_FW_PART_ID_G4_BL21:
991 part_info = &all->bl21;
993 case SWITCHTEC_FW_PART_ID_G4_IMG0:
994 part_info = &all->img0;
996 case SWITCHTEC_FW_PART_ID_G4_IMG1:
997 part_info = &all->img1;
999 case SWITCHTEC_FW_PART_ID_G4_CFG0:
1000 part_info = &all->cfg0;
1002 case SWITCHTEC_FW_PART_ID_G4_CFG1:
1003 part_info = &all->cfg1;
1005 case SWITCHTEC_FW_PART_ID_G4_NVLOG:
1006 part_info = &all->nvlog;
1008 case SWITCHTEC_FW_PART_ID_G4_SEEPROM:
1016 ret = switchtec_fw_info_metadata_gen4(dev, inf);
1018 inf->running =
true;
1028 inf->
part_addr = le32toh(part_info->part_start);
1029 inf->
part_len = le32toh(part_info->part_size_dw) * 4;
1030 inf->active = part_info->active;
1031 inf->running = part_info->is_using;
1032 inf->read_only = part_info->read_only;
1033 inf->valid = part_info->valid;
1037 return switchtec_fw_info_metadata_gen4(dev, inf);
1054 uint8_t subcmd = MRPC_PART_INFO_GET_ALL_INFO;
1057 if (info == NULL || nr_info == 0)
1060 if (dev->gen > SWITCHTEC_GEN3) {
1062 sizeof(subcmd), &all_info,
1066 all_info.firmware_version = le32toh(all_info.firmware_version);
1067 all_info.flash_size = le32toh(all_info.flash_size);
1068 all_info.device_id = le16toh(all_info.device_id);
1071 for (i = 0; i < nr_info; i++) {
1075 inf->
gen = dev->gen;
1076 inf->
type = switchtec_fw_id_to_type(inf);
1077 inf->active =
false;
1078 inf->running =
false;
1081 switch (info->
gen) {
1082 case SWITCHTEC_GEN3:
1083 ret = switchtec_fw_part_info_gen3(dev, inf);
1085 case SWITCHTEC_GEN4:
1086 case SWITCHTEC_GEN5:
1087 ret = switchtec_fw_part_info_gen4(dev, inf, &all_info);
1100 inf->metadata = NULL;
1107 int switchtec_get_device_id_bl2(
struct switchtec_dev *dev,
1108 unsigned short *device_id)
1111 uint8_t subcmd = MRPC_PART_INFO_GET_ALL_INFO;
1114 if (dev->gen != SWITCHTEC_GEN_UNKNOWN)
1118 sizeof(subcmd), &all_info,
1123 *device_id = le16toh(all_info.device_id);
1128 static long multicfg_subcmd(
struct switchtec_dev *dev, uint32_t subcmd,
1134 subcmd |= index << 8;
1135 subcmd = htole32(subcmd);
1137 ret =
switchtec_cmd(dev, MRPC_MULTI_CFG, &subcmd,
sizeof(subcmd),
1138 &result,
sizeof(result));
1145 static int get_multicfg(
struct switchtec_dev *dev,
1152 ret = multicfg_subcmd(dev, MRPC_MULTI_CFG_SUPPORTED, 0);
1161 ret = multicfg_subcmd(dev, MRPC_MULTI_CFG_COUNT, 0);
1168 for (i = 0; i < *nr_mult; i++) {
1169 info[i].
part_addr = multicfg_subcmd(dev,
1170 MRPC_MULTI_CFG_START_ADDR,
1172 info[i].
part_len = multicfg_subcmd(dev,
1173 MRPC_MULTI_CFG_LENGTH, i);
1174 strcpy(info[i].version,
"");
1179 ret = multicfg_subcmd(dev, MRPC_MULTI_CFG_ACTIVE, 0);
1184 info[ret].active = 1;
1189 static const enum switchtec_fw_image_part_id_gen3
1190 switchtec_fw_partitions_gen3[] = {
1191 SWITCHTEC_FW_PART_ID_G3_BOOT,
1192 SWITCHTEC_FW_PART_ID_G3_MAP0,
1193 SWITCHTEC_FW_PART_ID_G3_MAP1,
1194 SWITCHTEC_FW_PART_ID_G3_IMG0,
1195 SWITCHTEC_FW_PART_ID_G3_DAT0,
1196 SWITCHTEC_FW_PART_ID_G3_DAT1,
1197 SWITCHTEC_FW_PART_ID_G3_NVLOG,
1198 SWITCHTEC_FW_PART_ID_G3_IMG1,
1201 static const enum switchtec_fw_image_part_id_gen4
1202 switchtec_fw_partitions_gen4[] = {
1203 SWITCHTEC_FW_PART_ID_G4_MAP0,
1204 SWITCHTEC_FW_PART_ID_G4_MAP1,
1205 SWITCHTEC_FW_PART_ID_G4_KEY0,
1206 SWITCHTEC_FW_PART_ID_G4_KEY1,
1207 SWITCHTEC_FW_PART_ID_G4_BL20,
1208 SWITCHTEC_FW_PART_ID_G4_BL21,
1209 SWITCHTEC_FW_PART_ID_G4_CFG0,
1210 SWITCHTEC_FW_PART_ID_G4_CFG1,
1211 SWITCHTEC_FW_PART_ID_G4_IMG0,
1212 SWITCHTEC_FW_PART_ID_G4_IMG1,
1213 SWITCHTEC_FW_PART_ID_G4_NVLOG,
1214 SWITCHTEC_FW_PART_ID_G4_SEEPROM,
1217 static struct switchtec_fw_part_type *
1221 switch (info->
type) {
1222 case SWITCHTEC_FW_TYPE_BOOT:
return &summary->boot;
1223 case SWITCHTEC_FW_TYPE_MAP:
return &summary->map;
1224 case SWITCHTEC_FW_TYPE_IMG:
return &summary->img;
1225 case SWITCHTEC_FW_TYPE_CFG:
return &summary->cfg;
1226 case SWITCHTEC_FW_TYPE_NVLOG:
return &summary->nvlog;
1227 case SWITCHTEC_FW_TYPE_SEEPROM:
return &summary->seeprom;
1228 case SWITCHTEC_FW_TYPE_KEY:
return &summary->key;
1229 case SWITCHTEC_FW_TYPE_BL2:
return &summary->bl2;
1230 default:
return NULL;
1247 struct switchtec_fw_part_type *type;
1248 int nr_info, nr_mcfg = 16;
1253 case SWITCHTEC_GEN3:
1254 nr_info = ARRAY_SIZE(switchtec_fw_partitions_gen3);
1256 case SWITCHTEC_GEN4:
1257 case SWITCHTEC_GEN5:
1258 nr_info = ARRAY_SIZE(switchtec_fw_partitions_gen4);
1265 st_sz =
sizeof(*summary) +
sizeof(*summary->all) * (nr_info + nr_mcfg);
1267 summary = malloc(st_sz);
1271 memset(summary, 0, st_sz);
1272 summary->nr_info = nr_info;
1275 case SWITCHTEC_GEN3:
1276 for (i = 0; i < nr_info; i++)
1278 switchtec_fw_partitions_gen3[i];
1280 case SWITCHTEC_GEN4:
1281 case SWITCHTEC_GEN5:
1282 for (i = 0; i < nr_info; i++)
1284 switchtec_fw_partitions_gen4[i];
1292 if (ret != nr_info) {
1297 ret = get_multicfg(dev, &summary->all[nr_info], &nr_mcfg);
1303 for (i = 0; i < nr_info; i++) {
1304 type = switchtec_fw_type_ptr(summary, &summary->all[i]);
1309 if (summary->all[i].active)
1310 type->active = &summary->all[i];
1312 type->inactive = &summary->all[i];
1315 infp = &summary->mult_cfg;
1316 for (; i < nr_info + nr_mcfg; i++) {
1317 *infp = &summary->all[i];
1318 infp = &summary->all[i].next;
1332 for (i = 0; i < summary->nr_info; i++)
1333 free(summary->all[i].metadata);
1347 size_t len,
void *buf)
1354 unsigned char *cbuf = buf;
1358 size_t chunk_len = len;
1359 if (chunk_len > MRPC_MAX_DATA_LEN-8)
1360 chunk_len = MRPC_MAX_DATA_LEN-8;
1362 cmd.addr = htole32(addr);
1363 cmd.length = htole32(chunk_len);
1391 unsigned long addr,
size_t len,
1392 void (*progress_callback)(
int cur,
int tot))
1395 unsigned char buf[(MRPC_MAX_DATA_LEN-8)*4];
1397 size_t total_len = len;
1402 size_t chunk_len = len;
1403 if (chunk_len >
sizeof(buf))
1404 chunk_len =
sizeof(buf);
1411 while (total_wrote < ret) {
1412 wrote = write(fd, &buf[total_wrote],
1416 total_wrote += wrote;
1423 if (progress_callback)
1424 progress_callback(read, total_len);
1441 void (*progress_callback)(
int cur,
int tot))
1448 static int switchtec_fw_img_write_hdr_gen3(
int fd,
1454 memcpy(hdr.magic, ftr->magic,
sizeof(hdr.magic));
1455 hdr.image_len = ftr->image_len;
1457 hdr.load_addr = ftr->load_addr;
1458 hdr.version = ftr->version;
1459 hdr.header_crc = ftr->header_crc;
1460 hdr.image_crc = ftr->image_crc;
1462 if (hdr.type == SWITCHTEC_FW_PART_ID_G3_MAP1)
1463 hdr.type = SWITCHTEC_FW_PART_ID_G3_MAP0;
1464 else if (hdr.type == SWITCHTEC_FW_PART_ID_G3_IMG1)
1465 hdr.type = SWITCHTEC_FW_PART_ID_G3_IMG0;
1466 else if (hdr.type == SWITCHTEC_FW_PART_ID_G3_DAT1)
1467 hdr.type = SWITCHTEC_FW_PART_ID_G3_DAT0;
1469 return write(fd, &hdr,
sizeof(hdr));
1472 static int switchtec_fw_img_write_hdr_gen4(
int fd,
1478 ret = write(fd, hdr,
sizeof(*hdr));
1500 switch (info->
gen) {
1501 case SWITCHTEC_GEN3:
return switchtec_fw_img_write_hdr_gen3(fd, info);
1502 case SWITCHTEC_GEN4:
1503 case SWITCHTEC_GEN5:
return switchtec_fw_img_write_hdr_gen4(fd, info);
1526 .subcmd = MRPC_FWDNLD_BOOT_RO,
1532 uint8_t reserved[3];
1542 ret =
switchtec_cmd(dev, MRPC_FWDNLD, &subcmd,
sizeof(subcmd),
1543 &result,
sizeof(result));
1545 if (ret == ERR_SUBCMD_INVALID) {
1553 return result.status;
1566 .subcmd = MRPC_FWDNLD_BOOT_RO,
1576 return switchtec_cmd(dev, MRPC_FWDNLD, &subcmd,
sizeof(subcmd),