1
0
mirror of https://github.com/marqs85/ossc.git synced 2026-04-20 13:16:50 +00:00

fix firmware update functionality

This commit is contained in:
marqs
2025-05-03 16:14:58 +03:00
parent 30d403f157
commit 6198ce7d9e
13 changed files with 1174 additions and 264 deletions
+8
View File
@@ -82,6 +82,11 @@ avinput_t target_input;
alt_u8 pcm1862_active;
flash_ctrl_dev flashctrl_dev = {.regs = (volatile gen_flash_if_regs*)INTEL_GENERIC_SERIAL_FLASH_INTERFACE_TOP_0_AVL_CSR_BASE,
.flash_size = 0x0200000};
rem_update_dev rem_reconfig_dev = {.regs = (volatile rem_update_regs*)0x0002a000};
uint8_t sl_def_iv_x, sl_def_iv_y;
alt_u32 read_it2(alt_u32 regaddr);
@@ -951,6 +956,9 @@ int main()
// Start system timer
alt_timestamp_start();
// Write-protect flash
flash_write_protect(&flashctrl_dev, 1);
init_stat = init_hw();
if (init_stat >= 0) {
+20 -13
View File
@@ -20,6 +20,7 @@
#ifndef FIRMWARE_H_
#define FIRMWARE_H_
#include <stdint.h>
#include "alt_types.h"
#include "sysconfig.h"
@@ -40,23 +41,29 @@
#define FW_UPDATE_RETRIES 3
#define FW_IMAGE_ERROR 100
#define FW_HDR_ERROR 101
#define FW_HDR_CRC_ERROR 102
#define FW_DATA_CRC_ERROR 103
#define FW_UPD_CANCELLED 104
typedef struct {
char fw_key[4];
alt_u8 version_major;
alt_u8 version_minor;
uint8_t version_major;
uint8_t version_minor;
char version_suffix[8];
alt_u32 hdr_len;
alt_u32 data_len;
alt_u32 data_crc;
alt_u32 hdr_crc;
} fw_hdr;
uint32_t hdr_len;
uint32_t data_len;
uint32_t data_crc;
char padding[482];
uint32_t hdr_crc;
} __attribute__((packed)) fw_hdr;
typedef struct {
uint32_t unused[29];
uint32_t reconfig_start;
} rem_update_regs;
typedef struct {
volatile rem_update_regs *regs;
} rem_update_dev;
int fw_update();
void fw_update_commit(uint32_t* cluster_idx, uint8_t* databuf, uint32_t bytes_to_copy, uint16_t fs_csize, uint16_t fs_startsec);
#endif
+201 -168
View File
@@ -30,190 +30,223 @@
#include "lcd.h"
#include "utils.h"
#include "menu.h"
#include "ff.h"
#include "file.h"
#include "altera_avalon_pio_regs.h"
extern char menu_row1[LCD_ROW_LEN+1], menu_row2[LCD_ROW_LEN+1];
extern alt_u16 rc_keymap[REMOTE_MAX_KEYS];
extern SD_DEV sdcard_dev;
extern alt_u32 sys_ctrl;
extern flash_ctrl_dev flashctrl_dev;
extern rem_update_dev rem_reconfig_dev;
static int check_fw_header(alt_u8 *databuf, fw_hdr *hdr)
{
alt_u32 crcval, tmp;
strncpy(hdr->fw_key, (char*)databuf, 4);
if (strncmp(hdr->fw_key, "OSSC", 4))
return FW_IMAGE_ERROR;
hdr->version_major = databuf[4];
hdr->version_minor = databuf[5];
strncpy(hdr->version_suffix, (char*)(databuf+6), 8);
hdr->version_suffix[7] = 0;
memcpy(&tmp, databuf+14, 4);
hdr->hdr_len = bswap32(tmp);
memcpy(&tmp, databuf+18, 4);
hdr->data_len = bswap32(tmp);
memcpy(&tmp, databuf+22, 4);
hdr->data_crc = bswap32(tmp);
// Always at bytes [508-511]
memcpy(&tmp, databuf+508, 4);
hdr->hdr_crc = bswap32(tmp);
if (hdr->hdr_len < 26 || hdr->hdr_len > 508)
return FW_HDR_ERROR;
crcval = crc32(databuf, hdr->hdr_len, 1);
if (crcval != hdr->hdr_crc)
return FW_HDR_CRC_ERROR;
return 0;
}
static int check_fw_image(alt_u32 offset, alt_u32 size, alt_u32 golden_crc, alt_u8 *tmpbuf)
{
alt_u32 crcval=0, i, bytes_to_read;
//int fw_update(char *dirname, char *filename) {
int fw_update() {
FIL fw_file;
SDRESULTS res;
char dirname_root[10];
fw_hdr hdr;
int retval;
unsigned bytes_read, bytes_to_copy;
uint32_t crcval, hdr_len, btn_vec;
uint32_t cluster_idx[100]; // enough for >=4kB cluster size
uint8_t databuf[SD_BLK_SIZE]; // temp buffer for data
uint16_t fs_csize, fs_startsec, cl_iter, cl_soffs;
for (i=0; i<size; i=i+SD_BLK_SIZE) {
bytes_to_read = ((size-i < SD_BLK_SIZE) ? (size-i) : SD_BLK_SIZE);
res = SD_Read(&sdcard_dev, tmpbuf, (offset+i)/SD_BLK_SIZE, 0, bytes_to_read);
if (res != SD_OK)
return -res;
crcval = crc32(tmpbuf, bytes_to_read, (i==0));
}
if (crcval != golden_crc)
return FW_DATA_CRC_ERROR;
return 0;
}
int fw_update()
{
int retval, i;
int retries = FW_UPDATE_RETRIES;
char *errmsg;
alt_u8 databuf[SD_BLK_SIZE];
alt_u32 btn_vec;
alt_u32 bytes_to_rw;
fw_hdr fw_header;
#ifdef CHECK_STACK_USE
// estimate stack usage, assuming around here is the worst case (due to 512B databuf)
alt_u32 sp;
asm volatile("mv %0, sp" : "=r"(sp));
sniprintf(menu_row1, LCD_ROW_LEN+1, "Stack size:");
sniprintf(menu_row2, LCD_ROW_LEN+1, "%lu bytes", (ONCHIP_MEMORY2_0_BASE+ONCHIP_MEMORY2_0_SIZE_VALUE)-sp);
ui_disp_menu(1);
usleep(1000000);
#endif
retval = check_sdcard(databuf);
SPI_CS_High();
retval = file_mount();
if (retval != 0) {
retval = -retval;
goto failure;
printf("SD card not detected %d\n", retval);
return -1;
}
retval = check_fw_header(databuf, &fw_header);
if (retval != 0)
goto failure;
//sniprintf(dirname_root, sizeof(dirname_root), "/%s", dirname);
sniprintf(dirname_root, sizeof(dirname_root), "/");
f_chdir(dirname_root);
sniprintf(menu_row1, LCD_ROW_LEN+1, "Validating data");
sniprintf(menu_row2, LCD_ROW_LEN+1, "%u bytes", (unsigned)fw_header.data_len);
ui_disp_menu(1);
retval = check_fw_image(512, fw_header.data_len, fw_header.data_crc, databuf);
if (retval != 0)
goto failure;
if (!file_open(&fw_file, "ossc.bin")) {
strlcpy(menu_row1, "Checking FW", LCD_ROW_LEN+1);
strlcpy(menu_row2, "Please wait...", LCD_ROW_LEN+1);
ui_disp_menu(1);
sniprintf(menu_row1, LCD_ROW_LEN+1, "%u.%.2u%s%s", fw_header.version_major, fw_header.version_minor, (fw_header.version_suffix[0] == 0) ? "" : "-", fw_header.version_suffix);
strncpy(menu_row2, "Update? 1=Y, 2=N", LCD_ROW_LEN+1);
ui_disp_menu(1);
while (1) {
btn_vec = IORD_ALTERA_AVALON_PIO_DATA(PIO_1_BASE) & RC_MASK;
if (btn_vec == rc_keymap[RC_BTN1]) {
break;
} else if (btn_vec == rc_keymap[RC_BTN2]) {
retval = FW_UPD_CANCELLED;
goto failure;
if (f_read(&fw_file, &hdr, sizeof(hdr), &bytes_read) != F_OK) {
printf("FW hdr read error\n");
retval = -3;
goto close_file;
}
usleep(WAITLOOP_SLEEP_US);
hdr_len = bswap32(hdr.hdr_len);
if (strncmp(hdr.fw_key, "OSSC", 4) || (hdr_len < 26 || hdr_len > 508)) {
printf("Invalid FW header\n");
retval = -4;
goto close_file;
}
crcval = crc32((unsigned char *)&hdr, hdr_len, 1);
hdr.hdr_len = bswap32(hdr.hdr_len);
hdr.data_len = bswap32(hdr.data_len);
hdr.data_crc = bswap32(hdr.data_crc);
hdr.hdr_crc = bswap32(hdr.hdr_crc);
if (crcval != hdr.hdr_crc) {
printf("Invalid FW header CRC (0x%.8x instead of 0x%.8x)\n", crcval, hdr.hdr_crc);
retval = -5;
goto close_file;
}
printf("Firmware %u.%u%s%s\n", hdr.version_major, hdr.version_minor, hdr.version_suffix[0] ? "-" : "", hdr.version_suffix);
bytes_to_copy = hdr.data_len;
printf(" Image: %u bytes, crc 0x%.8x\n", hdr.data_len, hdr.data_crc);
if (hdr.data_len >= 16*FLASH_SECTOR_SIZE) {
printf("Image exceeds flash allocation\n");
retval = -6;
goto close_file;
}
sniprintf(menu_row1, LCD_ROW_LEN+1, "v%u.%u%s%s", hdr.version_major, hdr.version_minor, hdr.version_suffix[0] ? "-" : "", hdr.version_suffix);
sniprintf(menu_row2, LCD_ROW_LEN+1, "Update? 1=Y, 2=N");
ui_disp_menu(1);
while (1) {
btn_vec = IORD_ALTERA_AVALON_PIO_DATA(PIO_1_BASE) & RC_MASK;
if (btn_vec == rc_keymap[RC_BTN1]) {
break;
} else if (btn_vec == rc_keymap[RC_BTN2]) {
//set_func_ret_msg("Cancelled");
retval = 1;
goto close_file;
}
usleep(WAITLOOP_SLEEP_US);
}
strlcpy(menu_row2, "Please wait...", LCD_ROW_LEN+1);
ui_disp_menu(1);
// check if 512-byte header is on first or second cluster
fs_startsec = fw_file.obj.fs->database;
fs_csize = fw_file.obj.fs->csize;
if (fs_csize == 1) {
cl_iter = 1;
cl_soffs = 0;
cluster_idx[0] = fw_file.obj.sclust;
} else {
cl_iter = 0;
cl_soffs = 1;
}
// record cluster IDs to an array
if ((f_read_cc(&fw_file, &cluster_idx[cl_iter], bytes_to_copy, &bytes_read, (sizeof(cluster_idx)/sizeof(cluster_idx[0]))-1) != F_OK) || (bytes_read != bytes_to_copy)) {
printf("FW cluster error\n");
retval = -7;
goto close_file;
}
file_close(&fw_file);
f_chdir("/");
printf("Checking copied data...\n");
while (bytes_to_copy > 0) {
bytes_read = (bytes_to_copy > SD_BLK_SIZE) ? SD_BLK_SIZE : bytes_to_copy;
res = SD_Read(&sdcard_dev, databuf, ((cluster_idx[cl_iter]-2)*fs_csize+fs_startsec+cl_soffs), 0, bytes_read);
if (res != SD_OK) {
printf("FW data read error\n");
retval = -8;
goto close_file;
}
crcval = crc32((unsigned char *)&databuf, bytes_read, (bytes_to_copy==hdr.data_len));
bytes_to_copy -= bytes_read;
cl_soffs += 1;
if (cl_soffs == fs_csize) {
cl_iter += 1;
cl_soffs = 0;
}
}
if (crcval != hdr.data_crc) {
printf("Image: Invalid CRC (0x%.8x)\n", crcval);
retval = -9;
goto close_file;
}
printf("Starting update procedure...\n");
strlcpy(menu_row1, "Updating", LCD_ROW_LEN+1);
ui_disp_menu(1);
//disable video output
tvp_powerdown();
sys_ctrl |= VIDGEN_OFF;
IOWR_ALTERA_AVALON_PIO_DATA(PIO_0_BASE, sys_ctrl);
usleep(10000);
// No return from here
fw_update_commit(cluster_idx, databuf, hdr.data_len, fs_csize, fs_startsec);
return 0;
} else {
printf("FW file not found\n");
f_chdir("/");
return -2;
}
//disable video output
tvp_powerdown();
sys_ctrl |= VIDGEN_OFF;
IOWR_ALTERA_AVALON_PIO_DATA(PIO_0_BASE, sys_ctrl);
usleep(10000);
strncpy(menu_row1, "Updating FW", LCD_ROW_LEN+1);
update_init:
strncpy(menu_row2, "please wait...", LCD_ROW_LEN+1);
ui_disp_menu(1);
/*retval = copy_sd_to_flash(512/SD_BLK_SIZE, 0, fw_header.data_len, databuf);
if (retval != 0)
goto failure;
strncpy(menu_row1, "Verifying flash", LCD_ROW_LEN+1);
ui_disp_menu(1);
retval = verify_flash(0, fw_header.data_len, fw_header.data_crc, databuf);
if (retval != 0)
goto failure;*/
SPI_CS_High();
strncpy(menu_row1, "Firmware updated", LCD_ROW_LEN+1);
strncpy(menu_row2, "please restart", LCD_ROW_LEN+1);
ui_disp_menu(1);
while (1) {}
return 0;
failure:
SPI_CS_High();
switch (retval) {
case SD_NOINIT:
errmsg = "No SD card det.";
break;
case FW_IMAGE_ERROR:
errmsg = "Invalid image";
break;
case FW_HDR_ERROR:
errmsg = "Invalid header";
break;
case FW_HDR_CRC_ERROR:
errmsg = "Invalid hdr CRC";
break;
case FW_DATA_CRC_ERROR:
errmsg = "Invalid data CRC";
break;
case FW_UPD_CANCELLED:
errmsg = "Update cancelled";
break;
default:
errmsg = "SD/Flash error";
break;
}
strncpy(menu_row2, errmsg, LCD_ROW_LEN+1);
ui_disp_menu(1);
usleep(1000000);
// Critical error, retry update
if ((retval < 0) && (retries > 0)) {
sniprintf(menu_row1, LCD_ROW_LEN+1, "Retrying update");
retries--;
goto update_init;
}
render_osd_page();
return -1;
close_file:
file_close(&fw_file);
f_chdir("/");
return retval;
}
// commit FW update. Do not call functions located in flash during update
void __attribute__((noinline, flatten, noreturn, __section__(".text_bram"))) fw_update_commit(uint32_t* cluster_idx, uint8_t* databuf, uint32_t bytes_to_copy, uint16_t fs_csize, uint16_t fs_startsec) {
int i, sectors;
SDRESULTS res;
uint16_t cl_iter, cl_soffs;
uint32_t addr, bytes_read;
uint32_t *data_to;
flash_write_protect(&flashctrl_dev, 0);
// Erase sectors
addr = 0;
sectors = (bytes_to_copy/FLASH_SECTOR_SIZE) + ((bytes_to_copy % FLASH_SECTOR_SIZE) != 0);
data_to = (uint32_t*)(INTEL_GENERIC_SERIAL_FLASH_INTERFACE_TOP_0_AVL_MEM_BASE);
for (i=0; i<sectors; i++) {
flash_sector_erase(&flashctrl_dev, addr);
addr += FLASH_SECTOR_SIZE;
}
if (fs_csize == 1) {
cl_iter = 1;
cl_soffs = 0;
} else {
cl_iter = 0;
cl_soffs = 1;
}
// Write data
while (bytes_to_copy > 0) {
bytes_read = (bytes_to_copy > SD_BLK_SIZE) ? SD_BLK_SIZE : bytes_to_copy;
res = SD_Read(&sdcard_dev, databuf, ((cluster_idx[cl_iter]-2)*fs_csize+fs_startsec+cl_soffs), 0, bytes_read);
//TODO: retry if read fails
bytes_to_copy -= bytes_read;
for (i=0; i<bytes_read; i++)
databuf[i] = bitswap8(databuf[i]);
for (i=0; i<bytes_read; i+=4)
*data_to++ = *((uint32_t*)&databuf[i]);
cl_soffs += 1;
if (cl_soffs == fs_csize) {
cl_iter += 1;
cl_soffs = 0;
}
}
// flush command FIFO before FPGA reconfiguration start
*(volatile uint32_t*)(INTEL_GENERIC_SERIAL_FLASH_INTERFACE_TOP_0_AVL_MEM_BASE);
rem_reconfig_dev.regs->reconfig_start = 1;
while (1) {}
}
-4
View File
@@ -208,9 +208,7 @@ MENU(menu_scanlines, P99_PROTECT({ \
{ "Sl. alternating", OPT_AVCONFIG_SELECTION, { .sel = { &tc.sl_altern, OPT_WRAP, SETTING_ITEM(off_on_desc) } } },
{ LNG("Sl. alignment","スキャンラインポジション"), OPT_AVCONFIG_SELECTION, { .sel = { &tc.sl_id, OPT_WRAP, SETTING_ITEM(sl_id_desc) } } },
{ LNG("Sl. type","スキャンラインルイ"), OPT_AVCONFIG_SELECTION, { .sel = { &tc.sl_type, OPT_WRAP, SETTING_ITEM(sl_type_desc) } } },
#ifndef DEBUG
{ "< Custom Sl. >", OPT_SUBMENU, { .sub = { &menu_cust_sl, NULL, NULL } } },
#endif
}))
MENU(menu_postproc, P99_PROTECT({ \
@@ -251,11 +249,9 @@ MENU(menu_settings, P99_PROTECT({ \
{ LNG("<Load profile >","<プロファイルロード >"), OPT_FUNC_CALL, { .fun = { load_profile, &profile_arg_info } } },
{ LNG("<Save profile >","<プロファイルセーブ >"), OPT_FUNC_CALL, { .fun = { save_profile, &profile_arg_info } } },
{ LNG("<Reset settings>","<セッテイヲショキカ >"), OPT_FUNC_CALL, { .fun = { set_default_avconfig, NULL } } },
#ifndef DEBUG
{ LNG("<Import sett. >","<セッテイヨミコミ >"), OPT_FUNC_CALL, { .fun = { import_userdata, NULL } } },
{ LNG("<Export sett. >","<セッテイカキコミ >"), OPT_FUNC_CALL, { .fun = { export_userdata, NULL } } },
{ LNG("<Fw. update >","<ファームウェアアップデート>"), OPT_FUNC_CALL, { .fun = { fw_update, NULL } } },
#endif
}))
+1 -1
View File
@@ -25,7 +25,7 @@
#include "sysconfig.h"
#include "io.h"
inline unsigned char bitswap8(unsigned char v)
inline __attribute__((flatten, __section__(".text_bram"))) unsigned char bitswap8(unsigned char v)
{
return ((v * 0x0802LU & 0x22110LU) |
(v * 0x8020LU & 0x88440LU)) * 0x10101LU >> 16;
+4 -4
View File
@@ -94,11 +94,11 @@ DWORD __SD_Power_Of_Two(BYTE e)
return(partial);
}
inline void __SD_Assert(void){
inline void __attribute__((flatten, __section__(".text_bram"))) __SD_Assert(void){
SPI_CS_Low();
}
inline void __SD_Deassert(void){
inline void __attribute__((flatten, __section__(".text_bram"))) __SD_Deassert(void){
SPI_CS_High();
}
@@ -107,7 +107,7 @@ void __SD_Speed_Transfer(BYTE throttle) {
else SPI_Freq_Low();
}
BYTE __SD_Send_Cmd(BYTE cmd, DWORD arg)
BYTE __attribute__((noinline, flatten, __section__(".text_bram"))) __SD_Send_Cmd(BYTE cmd, DWORD arg)
{
BYTE wiredata[10];
BYTE crc, res;
@@ -361,7 +361,7 @@ SDRESULTS SD_Init(SD_DEV *dev)
#endif
}
SDRESULTS SD_Read(SD_DEV *dev, void *dat, DWORD sector, WORD ofs, WORD cnt)
SDRESULTS __attribute__((noinline, flatten, __section__(".text_bram"))) SD_Read(SD_DEV *dev, void *dat, DWORD sector, WORD ofs, WORD cnt)
{
#if defined(_M_IX86) // x86
// Check the sector query
+9 -8
View File
@@ -15,11 +15,11 @@ void SPI_Init (void) {
I2C_init(SD_SPI_BASE,ALT_CPU_FREQ,400000);
}
void SPI_W(const BYTE *wd, int len) {
void __attribute__((noinline, flatten, __section__(".text_bram"))) SPI_W(const BYTE *wd, int len) {
SPI_write(SD_SPI_BASE, wd, len);
}
void SPI_R(BYTE *rd, int len) {
void __attribute__((noinline, flatten, __section__(".text_bram"))) SPI_R(BYTE *rd, int len) {
SPI_read(SD_SPI_BASE, rd, len);
}
@@ -34,16 +34,17 @@ BYTE SPI_RW (BYTE d) {
return w;
}
void SPI_Release (void) {
void __attribute__((noinline, flatten, __section__(".text_bram"))) SPI_Release (void) {
SPI_CS_High();
return;
}
inline void SPI_CS_Low (void) {
inline void __attribute__((flatten, __section__(".text_bram"))) SPI_CS_Low (void) {
sys_ctrl &= ~SD_SPI_SS_N;
IOWR_ALTERA_AVALON_PIO_DATA(PIO_0_BASE, sys_ctrl);
}
inline void SPI_CS_High (void){
inline void __attribute__((flatten, __section__(".text_bram"))) SPI_CS_High (void){
sys_ctrl |= SD_SPI_SS_N;
IOWR_ALTERA_AVALON_PIO_DATA(PIO_0_BASE, sys_ctrl);
}
@@ -56,7 +57,7 @@ inline void SPI_Freq_Low (void) {
I2C_init(SD_SPI_BASE,ALT_CPU_FREQ,400000);
}
int SPI_Timer_On (WORD ms) {
int __attribute__((noinline, flatten, __section__(".text_bram"))) SPI_Timer_On (WORD ms) {
if (!sd_timer_ts) {
sd_timer_ts = alt_timestamp() + ms*(TIMER_0_FREQ/1000);
return 0;
@@ -64,11 +65,11 @@ int SPI_Timer_On (WORD ms) {
return 1;
}
inline BOOL SPI_Timer_Status (void) {
inline BOOL __attribute__((flatten, __section__(".text_bram"))) SPI_Timer_Status (void) {
return alt_timestamp() < sd_timer_ts;
}
inline void SPI_Timer_Off (void) {
inline void __attribute__((flatten, __section__(".text_bram"))) SPI_Timer_Off (void) {
sd_timer_ts = 0;
return;
}