[SC64][SW] Update: allow firmware update from the Flash memory

This commit is contained in:
Mateusz Faderewski 2024-05-03 19:17:52 +02:00
parent 0e868b5ad5
commit cf19dc6151
4 changed files with 72 additions and 20 deletions

View File

@ -8,10 +8,13 @@
bool flash_program (uint32_t src, uint32_t dst, uint32_t length) { bool flash_program (uint32_t src, uint32_t dst, uint32_t length) {
if (((src + length) > FLASH_ADDRESS) && (src < (FLASH_ADDRESS + FLASH_SIZE))) { if ((dst < FLASH_ADDRESS) || ((dst + length) > (FLASH_ADDRESS + FLASH_SIZE))) {
return true; return true;
} }
if ((dst < FLASH_ADDRESS) || ((dst + length) > (FLASH_ADDRESS + FLASH_SIZE))) { if ((src <= dst) && ((src + length) > dst)) {
return true;
}
if ((dst <= src) && ((dst + length) > src)) {
return true; return true;
} }
while (length > 0) { while (length > 0) {

View File

@ -8,6 +8,8 @@
#define SDRAM_ADDRESS (0x00000000UL) #define SDRAM_ADDRESS (0x00000000UL)
#define SDRAM_LENGTH (64 * 1024 * 1024) #define SDRAM_LENGTH (64 * 1024 * 1024)
#define FLASH_USABLE_LENGTH (14 * 1024 * 1024)
#define UPDATE_ADDRESS_END (SDRAM_ADDRESS + SDRAM_LENGTH + FLASH_USABLE_LENGTH)
#define UPDATE_MAGIC_START (0x54535055UL) #define UPDATE_MAGIC_START (0x54535055UL)
#define BOOTLOADER_ADDRESS (0x04E00000UL) #define BOOTLOADER_ADDRESS (0x04E00000UL)
@ -234,10 +236,10 @@ update_error_t update_prepare (uint32_t address, uint32_t length) {
uint32_t data_address; uint32_t data_address;
uint32_t data_length; uint32_t data_length;
if ((address >= (SDRAM_ADDRESS + SDRAM_LENGTH)) || (length > SDRAM_LENGTH)) { if ((address >= UPDATE_ADDRESS_END) || (length > (SDRAM_LENGTH + FLASH_USABLE_LENGTH))) {
return UPDATE_ERROR_ADDRESS; return UPDATE_ERROR_ADDRESS;
} }
if (end_address > (SDRAM_ADDRESS + SDRAM_LENGTH)) { if (end_address > UPDATE_ADDRESS_END) {
return UPDATE_ERROR_ADDRESS; return UPDATE_ERROR_ADDRESS;
} }

View File

@ -212,7 +212,7 @@ enum FirmwareCommands {
Backup(FirmwareArgs), Backup(FirmwareArgs),
/// Update SC64 firmware from provided file /// Update SC64 firmware from provided file
Update(FirmwareArgs), Update(FirmwareUpdateArgs),
} }
#[derive(Args)] #[derive(Args)]
@ -221,6 +221,16 @@ struct FirmwareArgs {
firmware: PathBuf, firmware: PathBuf,
} }
#[derive(Args)]
struct FirmwareUpdateArgs {
/// Path to the firmware file
firmware: PathBuf,
/// Put firmware update in the Flash memory instead of SDRAM
#[arg(long)]
use_flash_memory: bool,
}
#[derive(Args)] #[derive(Args)]
struct ServerArgs { struct ServerArgs {
/// Listen on provided address:port /// Listen on provided address:port
@ -738,8 +748,14 @@ fn handle_info_command(connection: Connection) -> Result<(), sc64::Error> {
println!(" LED blink: {}", state.led_enable); println!(" LED blink: {}", state.led_enable);
println!(" IS-Viewer 64 offset: 0x{:08X}", state.isv_address); println!(" IS-Viewer 64 offset: 0x{:08X}", state.isv_address);
println!("{}", "SummerCart64 diagnostic information:".bold()); println!("{}", "SummerCart64 diagnostic information:".bold());
println!(" Last PI address: 0x{:08X}", state.fpga_debug_data.last_pi_address); println!(
println!(" PI FIFO flags: {}", state.fpga_debug_data.pi_fifo_flags); " Last PI address: 0x{:08X}",
state.fpga_debug_data.last_pi_address
);
println!(
" PI FIFO flags: {}",
state.fpga_debug_data.pi_fifo_flags
);
println!(" Current CIC step: {}", state.fpga_debug_data.cic_step); println!(" Current CIC step: {}", state.fpga_debug_data.cic_step);
println!(" Diagnostic data: {}", state.diagnostic_data); println!(" Diagnostic data: {}", state.diagnostic_data);
@ -835,6 +851,12 @@ fn handle_firmware_command(
println!("{}", "Firmware metadata:".bold()); println!("{}", "Firmware metadata:".bold());
println!("{}", format!("{}", metadata).bright_blue().to_string()); println!("{}", format!("{}", metadata).bright_blue().to_string());
println!("{}", "Firmware file verification was successful".green()); println!("{}", "Firmware file verification was successful".green());
if args.use_flash_memory {
println!(
"{}",
"Warning: using Flash memory to perform firmware update".yellow()
);
}
let answer = prompt(format!("{}", "Continue with update process? [y/N] ".bold())); let answer = prompt(format!("{}", "Continue with update process? [y/N] ".bold()));
if answer.to_ascii_lowercase() != "y" { if answer.to_ascii_lowercase() != "y" {
println!("{}", "Firmware update process aborted".red()); println!("{}", "Firmware update process aborted".red());
@ -847,7 +869,7 @@ fn handle_firmware_command(
log_wait( log_wait(
format!("Updating firmware, this might take a while [{update_name}]"), format!("Updating firmware, this might take a while [{update_name}]"),
|| sc64.update_firmware(&firmware), || sc64.update_firmware(&firmware, args.use_flash_memory),
)?; )?;
Ok(()) Ok(())

View File

@ -89,7 +89,8 @@ const SRAM_1M_LENGTH: usize = 128 * 1024;
const BOOTLOADER_ADDRESS: u32 = 0x04E0_0000; const BOOTLOADER_ADDRESS: u32 = 0x04E0_0000;
const FIRMWARE_ADDRESS: u32 = 0x0010_0000; // Arbitrary offset in SDRAM memory const FIRMWARE_ADDRESS_SDRAM: u32 = 0x0010_0000; // Arbitrary offset in SDRAM memory
const FIRMWARE_ADDRESS_FLASH: u32 = 0x0410_0000; // Arbitrary offset in Flash memory
const FIRMWARE_UPDATE_TIMEOUT: Duration = Duration::from_secs(90); const FIRMWARE_UPDATE_TIMEOUT: Duration = Duration::from_secs(90);
const ISV_BUFFER_LENGTH: usize = 64 * 1024; const ISV_BUFFER_LENGTH: usize = 64 * 1024;
@ -668,19 +669,43 @@ impl SC64 {
pub fn backup_firmware(&mut self) -> Result<Vec<u8>, Error> { pub fn backup_firmware(&mut self) -> Result<Vec<u8>, Error> {
self.command_state_reset()?; self.command_state_reset()?;
let (status, length) = self.command_firmware_backup(FIRMWARE_ADDRESS)?; let (status, length) = self.command_firmware_backup(FIRMWARE_ADDRESS_SDRAM)?;
if !matches!(status, FirmwareStatus::Ok) { if !matches!(status, FirmwareStatus::Ok) {
return Err(Error::new( return Err(Error::new(
format!("Firmware backup error: {}", status).as_str(), format!("Firmware backup error: {}", status).as_str(),
)); ));
} }
self.command_memory_read(FIRMWARE_ADDRESS, length as usize) self.command_memory_read(FIRMWARE_ADDRESS_SDRAM, length as usize)
} }
pub fn update_firmware(&mut self, data: &[u8]) -> Result<(), Error> { pub fn update_firmware(&mut self, data: &[u8], use_flash_memory: bool) -> Result<(), Error> {
const FLASH_UPDATE_SUPPORTED_MINOR_VERSION: u16 = 19;
let status = if use_flash_memory {
let unsupported_version_error = Error::new(format!(
"Your firmware doesn't support updating from Flash memory, minimum required version: {}.{}.x",
SUPPORTED_MAJOR_VERSION, FLASH_UPDATE_SUPPORTED_MINOR_VERSION
).as_str());
self.command_version_get()
.and_then(|(major, minor, revision)| {
if major != SUPPORTED_MAJOR_VERSION
|| minor < FLASH_UPDATE_SUPPORTED_MINOR_VERSION
{
return Err(unsupported_version_error.clone());
} else {
Ok((major, minor, revision))
}
})
.map_err(|_| unsupported_version_error.clone())?;
self.command_state_reset()?; self.command_state_reset()?;
self.command_memory_write(FIRMWARE_ADDRESS, data)?; self.flash_erase(FIRMWARE_ADDRESS_FLASH, data.len())?;
let status = self.command_firmware_update(FIRMWARE_ADDRESS, data.len())?; self.command_memory_write(FIRMWARE_ADDRESS_FLASH, data)?;
self.command_flash_wait_busy(true)?;
self.command_firmware_update(FIRMWARE_ADDRESS_FLASH, data.len())?
} else {
self.command_state_reset()?;
self.command_memory_write(FIRMWARE_ADDRESS_SDRAM, data)?;
self.command_firmware_update(FIRMWARE_ADDRESS_SDRAM, data.len())?
};
if !matches!(status, FirmwareStatus::Ok) { if !matches!(status, FirmwareStatus::Ok) {
return Err(Error::new( return Err(Error::new(
format!("Firmware update verify error: {}", status).as_str(), format!("Firmware update verify error: {}", status).as_str(),