diff options
| author | Miika Pekkarinen <miipekk@ihme.org> | 2006-08-05 20:19:10 +0000 |
|---|---|---|
| committer | Miika Pekkarinen <miipekk@ihme.org> | 2006-08-05 20:19:10 +0000 |
| commit | 954b73265404075ec4d379ddea14e626113a8677 (patch) | |
| tree | 5c6ff0056ebd118aadb896856e7679a41c595cba /firmware | |
| parent | 85ba65d2a3fa3d10799efadbe3a33f026bf354df (diff) | |
| download | rockbox-954b73265404075ec4d379ddea14e626113a8677.zip rockbox-954b73265404075ec4d379ddea14e626113a8677.tar.gz rockbox-954b73265404075ec4d379ddea14e626113a8677.tar.bz2 rockbox-954b73265404075ec4d379ddea14e626113a8677.tar.xz | |
Initial support and use for EEPROM memory on H120 & H140 players when
Rockbox firmware has been flashed over original firmware (not yet
possible to do). Dircache & tagcache serialization for fast bootup
without the need to scan disk when Rockbox is in flash.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@10464 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware')
| -rw-r--r-- | firmware/SOURCES | 4 | ||||
| -rw-r--r-- | firmware/common/crc32.c | 4 | ||||
| -rw-r--r-- | firmware/common/dircache.c | 32 | ||||
| -rw-r--r-- | firmware/drivers/eeprom_24cxx.c | 6 | ||||
| -rw-r--r-- | firmware/eeprom_settings.c | 116 | ||||
| -rw-r--r-- | firmware/export/config-h100.h | 6 | ||||
| -rw-r--r-- | firmware/export/config-h120.h | 10 | ||||
| -rw-r--r-- | firmware/export/eeprom_settings.h | 48 | ||||
| -rw-r--r-- | firmware/export/system.h | 8 | ||||
| -rw-r--r-- | firmware/include/crc32.h | 2 | ||||
| -rw-r--r-- | firmware/powermgmt.c | 4 | ||||
| -rw-r--r-- | firmware/system.c | 21 |
12 files changed, 241 insertions, 20 deletions
diff --git a/firmware/SOURCES b/firmware/SOURCES index 8e2ca74..480c7ce 100644 --- a/firmware/SOURCES +++ b/firmware/SOURCES @@ -145,6 +145,10 @@ drivers/mas.c #ifdef IRIVER_H300_SERIES drivers/pcf50606.c #endif +#ifdef HAVE_EEPROM +drivers/eeprom_24cxx.c +eeprom_settings.c +#endif #ifdef IPOD_ARCH drivers/pcf50605.c #endif diff --git a/firmware/common/crc32.c b/firmware/common/crc32.c index 18ee6ac..21fefac 100644 --- a/firmware/common/crc32.c +++ b/firmware/common/crc32.c @@ -21,8 +21,10 @@ /* Tool function to calculate a CRC32 across some buffer */ /* third argument is either 0xFFFFFFFF to start or value from last piece */ -unsigned crc_32(unsigned char* buf, unsigned len, unsigned crc32) +unsigned crc_32(const void *src, unsigned len, unsigned crc32) { + const unsigned char *buf = (const unsigned char *)src; + /* CCITT standard polynomial 0x04C11DB7 */ static const unsigned crc32_lookup[16] = { /* lookup table for 4 bits at a time is affordable */ diff --git a/firmware/common/dircache.c b/firmware/common/dircache.c index 6167aa3..d2c77a2 100644 --- a/firmware/common/dircache.c +++ b/firmware/common/dircache.c @@ -402,7 +402,7 @@ static struct dircache_entry* dircache_get_entry(const char *path, return cache_entry; } -#if 0 +#if 1 /** * Function to load the internal cache structure from disk to initialize * the dircache really fast and little disk access. @@ -423,32 +423,41 @@ int dircache_load(const char *path) if (fd < 0) return -2; - dircache_root = (struct dircache_entry *)(((long)audiobuf & ~0x03) + 0x04); bytes_read = read(fd, &maindata, sizeof(struct dircache_maindata)); if (bytes_read != sizeof(struct dircache_maindata) - || (long)maindata.root_entry != (long)dircache_root || maindata.size <= 0) { + logf("Dircache file header error"); close(fd); return -3; } + dircache_root = buffer_alloc(0); + if ((long)maindata.root_entry != (long)dircache_root) + { + logf("Position missmatch"); + close(fd); + return -4; + } + + dircache_root = buffer_alloc(maindata.size + DIRCACHE_RESERVE); entry_count = maindata.entry_count; bytes_read = read(fd, dircache_root, MIN(DIRCACHE_LIMIT, maindata.size)); close(fd); if (bytes_read != maindata.size) + { + logf("Dircache read failed"); return -6; + } /* Cache successfully loaded. */ dircache_size = maindata.size; + allocated_size = dircache_size + DIRCACHE_RESERVE; + reserve_used = 0; logf("Done, %d KiB used", dircache_size / 1024); dircache_initialized = true; memset(fd_bindings, 0, sizeof(fd_bindings)); - - /* We have to long align the audiobuf to keep the buffer access fast. */ - audiobuf += (long)((dircache_size & ~0x03) + 0x04); - audiobuf += DIRCACHE_RESERVE; return 0; } @@ -472,7 +481,7 @@ int dircache_save(const char *path) return -1; logf("Saving directory cache"); - fd = open(path, O_WRONLY | O_CREAT); + fd = open(path, O_WRONLY | O_CREAT | O_TRUNC); maindata.magic = DIRCACHE_MAGIC; maindata.size = dircache_size; @@ -484,6 +493,7 @@ int dircache_save(const char *path) if (bytes_written != sizeof(struct dircache_maindata)) { close(fd); + logf("dircache: write failed #1"); return -2; } @@ -491,8 +501,11 @@ int dircache_save(const char *path) bytes_written = write(fd, dircache_root, dircache_size); close(fd); if (bytes_written != dircache_size) + { + logf("dircache: write failed #2"); return -3; - + } + return 0; } #endif /* #if 0 */ @@ -616,6 +629,7 @@ int dircache_build(int last_size) return -3; logf("Building directory cache"); + /* Background build, dircache has been previously allocated */ if (dircache_size > 0) { thread_enabled = true; diff --git a/firmware/drivers/eeprom_24cxx.c b/firmware/drivers/eeprom_24cxx.c index 4f7362e..33c02f1 100644 --- a/firmware/drivers/eeprom_24cxx.c +++ b/firmware/drivers/eeprom_24cxx.c @@ -308,7 +308,7 @@ bool eeprom_24cxx_read_byte(unsigned int address, char *c) bool eeprom_24cxx_write_byte(unsigned int address, char c) { int ret; - int count = 10; + int count = 100; if (address >= EEPROM_SIZE) { @@ -318,10 +318,6 @@ bool eeprom_24cxx_write_byte(unsigned int address, char c) do { ret = sw_i2c_write_byte(address, c); - if (ret < 0) - { - logf("EEPROM Fail: %d/%d", ret, address); - } } while (ret < 0 && count--) ; if (ret < 0) diff --git a/firmware/eeprom_settings.c b/firmware/eeprom_settings.c new file mode 100644 index 0000000..43f519d --- /dev/null +++ b/firmware/eeprom_settings.c @@ -0,0 +1,116 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2006 by Miika Pekkarinen + * + * All files in this archive are subject to the GNU General Public License. + * See the file COPYING in the source tree root for full license agreement. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +#include "eeprom_settings.h" +#include "eeprom_24cxx.h" +#include "crc32.h" + +#include "string.h" +#include "logf.h" + +struct eeprom_settings firmware_settings; + +static void reset_config(void) +{ + memset(&firmware_settings, 0, sizeof(struct eeprom_settings)); + firmware_settings.version = EEPROM_SETTINGS_VERSION; + firmware_settings.initialized = true; + firmware_settings.boot_disk = false; + firmware_settings.bl_version = 0; +} + +bool eeprom_settings_init(void) +{ + bool ret; + uint32_t sum; + + eeprom_24cxx_init(); + + /* Check if player has been flashed. */ + if (!detect_flashed_rockbox()) + { + memset(&firmware_settings, 0, sizeof(struct eeprom_settings)); + firmware_settings.initialized = false; + logf("Rockbox in flash is required"); + return false; + } + + ret = eeprom_24cxx_read(0, &firmware_settings, + sizeof(struct eeprom_settings)); + + if (!ret) + { + memset(&firmware_settings, 0, sizeof(struct eeprom_settings)); + firmware_settings.initialized = false; + return false; + } + + sum = crc_32(&firmware_settings, sizeof(struct eeprom_settings)-4, + 0xffffffff); + + if (firmware_settings.checksum != sum) + { + logf("Checksum mismatch"); + reset_config(); + return true; + } + + if (firmware_settings.version != EEPROM_SETTINGS_VERSION) + { + logf("Version mismatch"); + reset_config(); + return true; + } + +#ifndef BOOTLOADER + if (firmware_settings.bl_version < EEPROM_SETTINGS_BL_MINVER) + { + logf("Too old bootloader: %d", firmware_settings.bl_version); + reset_config(); + return true; + } +#endif + + return true; +} + +bool eeprom_settings_store(void) +{ + bool ret; + uint32_t sum; + + if (!firmware_settings.initialized || !detect_flashed_rockbox()) + { + logf("Rockbox in flash is required"); + return false; + } + + /* Update the checksum. */ + sum = crc_32(&firmware_settings, sizeof(struct eeprom_settings)-4, + 0xffffffff); + firmware_settings.checksum = sum; + ret = eeprom_24cxx_write(0, &firmware_settings, + sizeof(struct eeprom_settings)); + + if (!ret) + firmware_settings.initialized = false; + + return ret; +} + diff --git a/firmware/export/config-h100.h b/firmware/export/config-h100.h index 6d204c3..7310dfa 100644 --- a/firmware/export/config-h100.h +++ b/firmware/export/config-h100.h @@ -123,7 +123,10 @@ #define BOOTFILE_EXT "iriver" #define BOOTFILE "rockbox." BOOTFILE_EXT -#endif +/* Define this if there is an EEPROM chip */ +#define HAVE_EEPROM + +#endif /* !SIMULATOR */ /* Define this for S/PDIF input available */ #define HAVE_SPDIF_IN @@ -134,3 +137,4 @@ /* Define this if you can control the S/PDIF power */ #define HAVE_SPDIF_POWER #define SPDIF_POWER_INVERTED + diff --git a/firmware/export/config-h120.h b/firmware/export/config-h120.h index 5635a92..ca61813 100644 --- a/firmware/export/config-h120.h +++ b/firmware/export/config-h120.h @@ -118,7 +118,14 @@ #define BOOTFILE_EXT "iriver" #define BOOTFILE "rockbox." BOOTFILE_EXT -#endif +#define BOOTLOADER_ENTRYPOINT 0x001F0000 +#define FLASH_ENTRYPOINT 0x00001000 +#define FLASH_MAGIC 0xfbfbfbf1 + +/* Define this if there is an EEPROM chip */ +#define HAVE_EEPROM + +#endif /* !SIMULATOR */ /* Define this for S/PDIF input available */ #define HAVE_SPDIF_IN @@ -128,3 +135,4 @@ /* Define this if you can control the S/PDIF power */ #define HAVE_SPDIF_POWER + diff --git a/firmware/export/eeprom_settings.h b/firmware/export/eeprom_settings.h new file mode 100644 index 0000000..a3515bd --- /dev/null +++ b/firmware/export/eeprom_settings.h @@ -0,0 +1,48 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2006 by Miika Pekkarinen + * + * All files in this archive are subject to the GNU General Public License. + * See the file COPYING in the source tree root for full license agreement. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +#ifndef _EEPROM_SETTINGS_H_ +#define _EEPROM_SETTINGS_H_ + +#include <stdbool.h> +#include "inttypes.h" + +#define EEPROM_SETTINGS_VERSION 0x24c01001 +#define EEPROM_SETTINGS_BL_MINVER 7 + +struct eeprom_settings +{ + long version; /* Settings version number */ + bool initialized; /* Is eeprom_settings ready to be used */ + bool disk_clean; /* Is disk intact from last reboot */ + bool boot_disk; /* Load firmware from disk (default=FLASH) */ + uint8_t bl_version; /* Installed bootloader version */ + + /* This must be the last entry */ + uint32_t checksum; /* Checksum of this structure */ +}; + +extern struct eeprom_settings firmware_settings; + +bool detect_flashed_rockbox(void); +bool eeprom_settings_init(void); +bool eeprom_settings_store(void); + +#endif + diff --git a/firmware/export/system.h b/firmware/export/system.h index dae5d95..1b326e1 100644 --- a/firmware/export/system.h +++ b/firmware/export/system.h @@ -45,6 +45,14 @@ static inline void udelay(unsigned usecs) } #endif +struct flash_header { + unsigned long magic; + unsigned long length; + char version[32]; +}; + +bool detect_flashed_rockbox(void); + #ifdef HAVE_ADJUSTABLE_CPU_FREQ #define FREQ cpu_frequency void set_cpu_frequency(long frequency); diff --git a/firmware/include/crc32.h b/firmware/include/crc32.h index 5e998ab..a2b7ae2 100644 --- a/firmware/include/crc32.h +++ b/firmware/include/crc32.h @@ -19,7 +19,7 @@ #ifndef _CRC32_H #define _CRC32_H -unsigned crc_32(unsigned char* buf, unsigned len, unsigned crc32); +unsigned crc_32(const void *src, unsigned len, unsigned crc32); #endif diff --git a/firmware/powermgmt.c b/firmware/powermgmt.c index 4bccd4e..a8e641e 100644 --- a/firmware/powermgmt.c +++ b/firmware/powermgmt.c @@ -993,8 +993,8 @@ void sys_poweroff(void) { logf("sys_poweroff()"); /* If the main thread fails to shut down the system, we will force a - power off after an 8 second timeout */ - shutdown_timeout = HZ*8; + power off after an 20 second timeout */ + shutdown_timeout = HZ*20; queue_post(&button_queue, SYS_POWEROFF, NULL); } diff --git a/firmware/system.c b/firmware/system.c index 1874c04..bb09dbc 100644 --- a/firmware/system.c +++ b/firmware/system.c @@ -24,6 +24,8 @@ #include "system.h" #include "kernel.h" #include "timer.h" +#include "inttypes.h" +#include "string.h" #ifndef SIMULATOR long cpu_frequency = CPU_FREQ; @@ -76,6 +78,25 @@ void cpu_idle_mode(bool on_off) #endif +#if defined(IRIVER_H100_SERIES) && !defined(SIMULATOR) +bool detect_flashed_rockbox(void) +{ + struct flash_header hdr; + uint8_t *src = (uint8_t *)FLASH_ENTRYPOINT; + + memcpy(&hdr, src, sizeof(struct flash_header)); + if (hdr.magic != FLASH_MAGIC) + return false; + + return true; +} +#else +bool detect_flashed_rockbox(void) +{ + return false; +} +#endif + #if CONFIG_CPU == TCC730 void* volatile interrupt_vector[16] __attribute__ ((section(".idata"))); |