diff --git a/util/amdfwtool/amdfwtool.c b/util/amdfwtool/amdfwtool.c index a5e5110856..14ffdb3d88 100644 --- a/util/amdfwtool/amdfwtool.c +++ b/util/amdfwtool/amdfwtool.c @@ -215,7 +215,31 @@ static void usage(void) printf("-q | --anywhere Use any 64-byte aligned addr for Directory\n"); printf("-R | --sharedmem Location of PSP/FW shared memory\n"); printf("-P | --sharedmem-size Maximum size of the PSP/FW shared memory area\n"); + printf("-C | --soc-name Specify SOC name. Supported names are\n"); + printf(" Stoneyridge, Raven, Picasso, Renoir or Lucienne"); printf("-h | --help show this help\n"); + printf("\nEmbedded Firmware Structure options used by the PSP:\n"); + printf("--spi-speed SPI fast speed to place in EFS Table\n"); + printf(" 0x0 66.66Mhz\n"); + printf(" 0x1 33.33MHz\n"); + printf(" 0x2 22.22MHz\n"); + printf(" 0x3 16.66MHz\n"); + printf(" 0x4 100MHz\n"); + printf(" 0x5 800KHz\n"); + printf("--spi-read-mode SPI read mode to place in EFS Table\n"); + printf(" 0x0 Normal Read (up to 33M)\n"); + printf(" 0x1 Reserved\n"); + printf(" 0x2 Dual IO (1-1-2)\n"); + printf(" 0x3 Quad IO (1-1-4)\n"); + printf(" 0x4 Dual IO (1-2-2)\n"); + printf(" 0x5 Quad IO (1-4-4)\n"); + printf(" 0x6 Normal Read (up to 66M)\n"); + printf(" 0x7 Fast Read\n"); + printf("--spi-micron-flag Micron SPI part support for RV and later SOC\n"); + printf(" 0x0 Micron parts are not used\n"); + printf(" 0x1 Micron parts are always used\n"); + printf(" 0x2 Micron parts optional, this option is only\n"); + printf(" supported with RN/LCN SOC\n"); } typedef enum _amd_bios_type { @@ -413,7 +437,26 @@ typedef struct _embedded_firmware { uint32_t bios0_entry; /* todo: add way to select correct entry */ uint32_t bios1_entry; uint32_t bios2_entry; - uint32_t reserved[0x2c]; /* 0x24 - 0x4f */ + uint32_t second_gen_efs; + uint32_t bios3_entry; + uint32_t reserved_2Ch; + uint32_t promontory_fw_ptr; + uint32_t lp_promontory_fw_ptr; + uint32_t reserved_38h; + uint32_t reserved_3Ch; + uint8_t spi_readmode_f15_mod_60_6f; + uint8_t fast_speed_new_f15_mod_60_6f; + uint8_t reserved_42h; + uint8_t spi_readmode_f17_mod_00_2f; + uint8_t spi_fastspeed_f17_mod_00_2f; + uint8_t qpr_dummy_cycle_f17_mod_00_2f; + uint8_t reserved_46h; + uint8_t spi_readmode_f17_mod_30_3f; + uint8_t spi_fastspeed_f17_mod_30_3f; + uint8_t micron_detect_f17_mod_30_3f; + uint8_t reserved_4Ah; + uint8_t reserved_4Bh; + uint32_t reserved_4Ch; } __attribute__((packed, aligned(16))) embedded_firmware; typedef struct _psp_directory_header { @@ -1038,8 +1081,16 @@ static void integrate_bios_firmwares(context *ctx, fill_dir_header(biosdir, count, cookie); } -// Unused values: CDE -static const char *optstring = "x:i:g:AMS:p:b:s:r:k:c:n:d:t:u:w:m:T:z:J:B:K:L:Y:N:UW:I:a:Q:V:e:v:j:y:G:O:X:F:H:o:f:l:hZ:qR:P:"; + +enum { + /* begin after ASCII characters */ + LONGOPT_SPI_READ_MODE = 256, + LONGOPT_SPI_SPEED = 257, + LONGOPT_SPI_MICRON_FLAG = 258, +}; + +// Unused values: DE +static const char *optstring = "x:i:g:AMS:p:b:s:r:k:c:n:d:t:u:w:m:T:z:J:B:K:L:Y:N:UW:I:a:Q:V:e:v:j:y:G:O:X:F:H:o:f:l:hZ:qR:P:C:"; static struct option long_options[] = { {"xhci", required_argument, 0, 'x' }, @@ -1086,6 +1137,10 @@ static struct option long_options[] = { {"mp2-config", required_argument, 0, 'X' }, {"apob-nv-base", required_argument, 0, 'F' }, {"apob-nv-size", required_argument, 0, 'H' }, + /* Embedded Firmware Structure items*/ + {"spi-read-mode", required_argument, 0, LONGOPT_SPI_READ_MODE }, + {"spi-speed", required_argument, 0, LONGOPT_SPI_SPEED }, + {"spi-micron-flag", required_argument, 0, LONGOPT_SPI_MICRON_FLAG }, /* other */ {"output", required_argument, 0, 'o' }, {"flashsize", required_argument, 0, 'f' }, @@ -1093,6 +1148,7 @@ static struct option long_options[] = { {"anywhere", no_argument, 0, 'q' }, {"sharedmem", required_argument, 0, 'R' }, {"sharedmem-size", required_argument, 0, 'P' }, + {"soc-name", required_argument, 0, 'C' }, {"help", no_argument, 0, 'h' }, {NULL, 0, 0, 0 } }; @@ -1178,6 +1234,91 @@ static void register_fw_addr(amd_bios_type type, char *src_str, } } +enum platform { + PLATFORM_UNKNOWN, + PLATFORM_STONEYRIDGE, + PLATFORM_RAVEN, + PLATFORM_PICASSO, + PLATFORM_RENOIR, + PLATFORM_LUCIENNE, +}; + +static int set_efs_table(uint8_t soc_id, embedded_firmware *amd_romsig, + uint8_t efs_spi_readmode, uint8_t efs_spi_speed, + uint8_t efs_spi_micron_flag) +{ + if ((efs_spi_readmode == 0xFF) || (efs_spi_speed == 0xFF)) { + printf("Error: EFS read mode and SPI speed must be set\n"); + return 1; + } + switch (soc_id) { + case PLATFORM_STONEYRIDGE: + amd_romsig->second_gen_efs = 0; + amd_romsig->spi_readmode_f15_mod_60_6f = efs_spi_readmode; + amd_romsig->fast_speed_new_f15_mod_60_6f = efs_spi_speed; + break; + case PLATFORM_RAVEN: + case PLATFORM_PICASSO: + amd_romsig->second_gen_efs = 0; + amd_romsig->spi_readmode_f17_mod_00_2f = efs_spi_readmode; + amd_romsig->spi_fastspeed_f17_mod_00_2f = efs_spi_speed; + switch (efs_spi_micron_flag) { + case 0: + amd_romsig->qpr_dummy_cycle_f17_mod_00_2f = 0xff; + break; + case 1: + amd_romsig->qpr_dummy_cycle_f17_mod_00_2f = 0xa; + break; + default: + printf("Error: EFS Micron flag must be correctly set.\n\n"); + return 1; + } + break; + case PLATFORM_RENOIR: + case PLATFORM_LUCIENNE: + amd_romsig->second_gen_efs = 1; + amd_romsig->spi_readmode_f17_mod_30_3f = efs_spi_readmode; + amd_romsig->spi_fastspeed_f17_mod_30_3f = efs_spi_speed; + switch (efs_spi_micron_flag) { + case 0: + amd_romsig->micron_detect_f17_mod_30_3f = 0xff; + break; + case 1: + amd_romsig->micron_detect_f17_mod_30_3f = 0xaa; + break; + case 2: + amd_romsig->micron_detect_f17_mod_30_3f = 0x55; + break; + default: + printf("Error: EFS Micron flag must be correctly set.\n\n"); + return 1; + } + break; + case PLATFORM_UNKNOWN: + default: + printf("Error: Invalid SOC name.\n\n"); + return 1; + } + return 0; +} + +static int identify_platform(char *soc_name) +{ + if (!strcasecmp(soc_name, "Stoneyridge")) + return PLATFORM_STONEYRIDGE; + else if (!strcasecmp(soc_name, "Raven")) + return PLATFORM_RAVEN; + else if (!strcasecmp(soc_name, "Picasso")) + return PLATFORM_PICASSO; + else if (!strcasecmp(soc_name, "Renoir")) + return PLATFORM_RENOIR; + else if (!strcasecmp(soc_name, "Lucienne")) + return PLATFORM_LUCIENNE; + else + return PLATFORM_UNKNOWN; + +} + int main(int argc, char **argv) { int c; @@ -1200,6 +1341,11 @@ int main(int argc, char **argv) bool any_location = 0; uint32_t romsig_offset; uint32_t rom_base_address; + uint8_t soc_id = PLATFORM_UNKNOWN; + uint8_t efs_spi_readmode = 0xff; + uint8_t efs_spi_speed = 0xff; + uint8_t efs_spi_micron_flag = 0xff; + int multi = 0; while (1) { @@ -1394,6 +1540,26 @@ int main(int argc, char **argv) register_fw_filename(AMD_FW_PSP_VERSTAGE, sub, optarg); sub = instance = 0; break; + case 'C': + soc_id = identify_platform(optarg); + if (soc_id == PLATFORM_UNKNOWN) { + printf("Error: Invalid SOC name specified\n\n"); + retval = 1; + } + sub = instance = 0; + break; + case LONGOPT_SPI_READ_MODE: + efs_spi_readmode = strtoull(optarg, NULL, 16); + sub = instance = 0; + break; + case LONGOPT_SPI_SPEED: + efs_spi_speed = strtoull(optarg, NULL, 16); + sub = instance = 0; + break; + case LONGOPT_SPI_MICRON_FLAG: + efs_spi_micron_flag = strtoull(optarg, NULL, 16); + sub = instance = 0; + break; case 'o': output = optarg; break; @@ -1512,6 +1678,17 @@ int main(int argc, char **argv) amd_romsig->gec_entry = 0; amd_romsig->xhci_entry = 0; + if (soc_id != PLATFORM_UNKNOWN) { + retval = set_efs_table(soc_id, amd_romsig, efs_spi_readmode, + efs_spi_speed, efs_spi_micron_flag); + if (retval) { + printf("ERROR: Failed to initialize EFS table!\n"); + return retval; + } + } else { + printf("WARNING: No SOC name specified.\n"); + } + integrate_firmwares(&ctx, amd_romsig, amd_fw_table); ctx.current = ALIGN(ctx.current, 0x10000U); /* TODO: is it necessary? */