From cf19dc6151f9667776d7588bc5fe10bee865e32f Mon Sep 17 00:00:00 2001 From: Mateusz Faderewski Date: Fri, 3 May 2024 19:17:52 +0200 Subject: [PATCH] [SC64][SW] Update: allow firmware update from the Flash memory --- sw/controller/src/flash.c | 7 +++++-- sw/controller/src/update.c | 16 ++++++++------- sw/deployer/src/main.rs | 30 ++++++++++++++++++++++++---- sw/deployer/src/sc64/mod.rs | 39 ++++++++++++++++++++++++++++++------- 4 files changed, 72 insertions(+), 20 deletions(-) diff --git a/sw/controller/src/flash.c b/sw/controller/src/flash.c index 8ab204a..12c355b 100644 --- a/sw/controller/src/flash.c +++ b/sw/controller/src/flash.c @@ -8,10 +8,13 @@ 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; } - 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; } while (length > 0) { diff --git a/sw/controller/src/update.c b/sw/controller/src/update.c index 44b4d5e..3a25cc6 100644 --- a/sw/controller/src/update.c +++ b/sw/controller/src/update.c @@ -6,12 +6,14 @@ #include "vendor.h" -#define SDRAM_ADDRESS (0x00000000UL) -#define SDRAM_LENGTH (64 * 1024 * 1024) +#define SDRAM_ADDRESS (0x00000000UL) +#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 BOOTLOADER_ADDRESS (0x04E00000UL) -#define BOOTLOADER_LENGTH (0x001E0000UL) +#define UPDATE_MAGIC_START (0x54535055UL) +#define BOOTLOADER_ADDRESS (0x04E00000UL) +#define BOOTLOADER_LENGTH (0x001E0000UL) typedef enum { @@ -234,10 +236,10 @@ update_error_t update_prepare (uint32_t address, uint32_t length) { uint32_t data_address; 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; } - if (end_address > (SDRAM_ADDRESS + SDRAM_LENGTH)) { + if (end_address > UPDATE_ADDRESS_END) { return UPDATE_ERROR_ADDRESS; } diff --git a/sw/deployer/src/main.rs b/sw/deployer/src/main.rs index 5cde6be..3de91a0 100644 --- a/sw/deployer/src/main.rs +++ b/sw/deployer/src/main.rs @@ -212,7 +212,7 @@ enum FirmwareCommands { Backup(FirmwareArgs), /// Update SC64 firmware from provided file - Update(FirmwareArgs), + Update(FirmwareUpdateArgs), } #[derive(Args)] @@ -221,6 +221,16 @@ struct FirmwareArgs { 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)] struct ServerArgs { /// 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!(" IS-Viewer 64 offset: 0x{:08X}", state.isv_address); println!("{}", "SummerCart64 diagnostic information:".bold()); - println!(" Last PI address: 0x{:08X}", state.fpga_debug_data.last_pi_address); - println!(" PI FIFO flags: {}", state.fpga_debug_data.pi_fifo_flags); + println!( + " 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!(" Diagnostic data: {}", state.diagnostic_data); @@ -835,6 +851,12 @@ fn handle_firmware_command( println!("{}", "Firmware metadata:".bold()); println!("{}", format!("{}", metadata).bright_blue().to_string()); 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())); if answer.to_ascii_lowercase() != "y" { println!("{}", "Firmware update process aborted".red()); @@ -847,7 +869,7 @@ fn handle_firmware_command( log_wait( format!("Updating firmware, this might take a while [{update_name}]"), - || sc64.update_firmware(&firmware), + || sc64.update_firmware(&firmware, args.use_flash_memory), )?; Ok(()) diff --git a/sw/deployer/src/sc64/mod.rs b/sw/deployer/src/sc64/mod.rs index f3842fc..b0179f3 100644 --- a/sw/deployer/src/sc64/mod.rs +++ b/sw/deployer/src/sc64/mod.rs @@ -89,7 +89,8 @@ const SRAM_1M_LENGTH: usize = 128 * 1024; 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 ISV_BUFFER_LENGTH: usize = 64 * 1024; @@ -668,19 +669,43 @@ impl SC64 { pub fn backup_firmware(&mut self) -> Result, Error> { 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) { return Err(Error::new( 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> { - self.command_state_reset()?; - self.command_memory_write(FIRMWARE_ADDRESS, data)?; - let status = self.command_firmware_update(FIRMWARE_ADDRESS, data.len())?; + 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.flash_erase(FIRMWARE_ADDRESS_FLASH, 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) { return Err(Error::new( format!("Firmware update verify error: {}", status).as_str(),