mirror of
https://github.com/Polprzewodnikowy/SummerCart64.git
synced 2024-11-21 21:49:15 +01:00
[SC64][SW] Update: allow firmware update from the Flash memory
This commit is contained in:
parent
0e868b5ad5
commit
cf19dc6151
@ -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) {
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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(())
|
||||||
|
@ -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(),
|
||||||
|
Loading…
Reference in New Issue
Block a user