summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/debug_menu.c34
-rw-r--r--apps/plugin.c3
-rw-r--r--apps/plugin.h7
-rw-r--r--apps/plugins/firmware_flash.c4
-rw-r--r--apps/plugins/rockbox_flash.c3
-rw-r--r--firmware/export/system.h11
-rw-r--r--firmware/system.c48
7 files changed, 104 insertions, 6 deletions
diff --git a/apps/debug_menu.c b/apps/debug_menu.c
index 9fd2e33749..987007caad 100644
--- a/apps/debug_menu.c
+++ b/apps/debug_menu.c
@@ -122,7 +122,7 @@ bool dbg_os(void)
usage = thread_stack_usage(currval);
snprintf(buf, 32, "%d: %d%% ", currval, usage);
lcd_puts(0, 1, buf);
-
+
button = button_get_w_tmo(HZ/10);
switch(button)
@@ -130,7 +130,7 @@ bool dbg_os(void)
case BUTTON_STOP:
return false;
- case BUTTON_LEFT:
+ case BUTTON_LEFT:
currval--;
if(currval < 0)
currval = num_threads-1;
@@ -301,6 +301,7 @@ bool dbg_hw_info(void)
bool got_id; /* flag if we managed to get the flash IDs */
unsigned rom_crc = 0xFFFF; /* CRC16 of the boot ROM */
bool has_bootrom; /* flag for boot ROM present */
+ int oldmode; /* saved memory guard mode */
if(PADR & 0x400)
usb_polarity = 0; /* Negative */
@@ -312,6 +313,8 @@ bool dbg_hw_info(void)
else
pr_polarity = 1; /* Positive */
+ oldmode = system_memory_guard(MEMGUARD_NONE); /* disable memory guard */
+
/* get flash ROM type */
got_id = dbg_flash_id(&manu, &id, 0x5555, 0x2AAA); /* try SST, Atmel, NexFlash */
if (!got_id)
@@ -325,6 +328,8 @@ bool dbg_hw_info(void)
rom_crc = crc_16((unsigned char*)0x0000, 64*1024);
}
+ system_memory_guard(oldmode); /* re-enable memory guard */
+
lcd_setmargins(0, 0);
lcd_setfont(FONT_SYSFIXED);
lcd_clear_display();
@@ -389,12 +394,15 @@ bool dbg_hw_info(void)
bool got_id; /* flag if we managed to get the flash IDs */
unsigned rom_crc = 0xFFFF; /* CRC16 of the boot ROM */
bool has_bootrom; /* flag for boot ROM present */
+ int oldmode; /* saved memory guard mode */
if(PADR & 0x400)
usb_polarity = 0; /* Negative */
else
usb_polarity = 1; /* Positive */
+ oldmode = system_memory_guard(MEMGUARD_NONE); /* disable memory guard */
+
/* get flash ROM type */
got_id = dbg_flash_id(&manu, &id, 0x5555, 0x2AAA); /* try SST, Atmel, NexFlash */
if (!got_id)
@@ -407,6 +415,8 @@ bool dbg_hw_info(void)
/* calculate CRC16 checksum of boot ROM */
rom_crc = crc_16((unsigned char*)0x0000, 64*1024);
}
+
+ system_memory_guard(oldmode); /* re-enable memory guard */
lcd_clear_display();
@@ -579,7 +589,7 @@ bool dbg_ports(void)
snprintf(buf, 32, "ATA: %s, 0x%x",
ata_device?"slave":"master", ata_io_address);
lcd_puts(0, 7, buf);
-
+
lcd_update();
button = button_get_w_tmo(HZ/10);
@@ -1440,6 +1450,7 @@ static bool dbg_disk_info(void)
bool dbg_save_roms(void)
{
int fd;
+ int oldmode = system_memory_guard(MEMGUARD_NONE);
fd = creat("/internal_rom_0000-FFFF.bin", O_WRONLY);
if(fd >= 0)
@@ -1455,6 +1466,7 @@ bool dbg_save_roms(void)
close(fd);
}
+ system_memory_guard(oldmode);
return false;
}
@@ -1510,6 +1522,21 @@ bool dbg_screendump(void)
}
#endif
+bool dbg_set_memory_guard(void)
+{
+ static const struct opt_items names[MAXMEMGUARD] = {
+ { "None", -1 },
+ { "Flash ROM writes", -1 },
+ { "Zero area (all)", -1 }
+ };
+ int mode = system_memory_guard(MEMGUARD_KEEP);
+
+ set_option( "Catch mem accesses", &mode, INT, names, MAXMEMGUARD, NULL);
+ system_memory_guard(mode);
+
+ return false;
+}
+
bool debug_menu(void)
{
int m;
@@ -1524,6 +1551,7 @@ bool debug_menu(void)
#endif /* HAVE_RTC */
#endif /* HAVE_LCD_BITMAP */
{ "View OS stacks", dbg_os },
+ { "Catch mem accesses", dbg_set_memory_guard },
#ifdef HAVE_MAS3507D
{ "View MAS info", dbg_mas_info },
#endif
diff --git a/apps/plugin.c b/apps/plugin.c
index a7ae34f67e..6892cb957f 100644
--- a/apps/plugin.c
+++ b/apps/plugin.c
@@ -259,6 +259,9 @@ static const struct plugin_api rockbox_api = {
mpeg_get_file_pos,
find_next_frame,
mpeg_get_last_header,
+#ifndef SIMULATOR
+ system_memory_guard,
+#endif
};
int plugin_load(const char* plugin, void* parameter)
diff --git a/apps/plugin.h b/apps/plugin.h
index 43f8b897c3..078dc12217 100644
--- a/apps/plugin.h
+++ b/apps/plugin.h
@@ -51,7 +51,7 @@
#ifdef PLUGIN
#if defined(DEBUG) || defined(SIMULATOR)
-#define DEBUGF rb->debugf
+#define DEBUGF rb->debugf
#define LDEBUGF rb->debugf
#else
#define DEBUGF(...)
@@ -60,7 +60,7 @@
#endif
/* increase this every time the api struct changes */
-#define PLUGIN_API_VERSION 26
+#define PLUGIN_API_VERSION 27
/* update this to latest version if a change to the api struct breaks
backwards compatibility (and please take the opportunity to sort in any
@@ -295,6 +295,9 @@ struct plugin_api {
unsigned long (*find_next_frame)(int fd, int *offset,
int max_offset, unsigned long last_header);
unsigned long (*mpeg_get_last_header)(void);
+#ifndef SIMULATOR
+ int (*system_memory_guard)(int newmode);
+#endif
};
/* defined by the plugin loader (plugin.c) */
diff --git a/apps/plugins/firmware_flash.c b/apps/plugins/firmware_flash.c
index 8f7f187607..751284aed1 100644
--- a/apps/plugins/firmware_flash.c
+++ b/apps/plugins/firmware_flash.c
@@ -1010,6 +1010,8 @@ void DoUserDialog(char* filename)
enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
{
+ int oldmode;
+
/* this macro should be called as the first thing you do in the plugin.
it test that the api version and model the plugin was compiled for
matches the machine it is running on */
@@ -1018,7 +1020,9 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
rb = api; /* copy to global api pointer */
/* now go ahead and have fun! */
+ oldmode = rb->system_memory_guard(MEMGUARD_NONE); /*disable memory guard */
DoUserDialog((char*) parameter);
+ rb->system_memory_guard(oldmode); /* re-enable memory guard */
return PLUGIN_OK;
}
diff --git a/apps/plugins/rockbox_flash.c b/apps/plugins/rockbox_flash.c
index 3bb8476b43..e393f20058 100644
--- a/apps/plugins/rockbox_flash.c
+++ b/apps/plugins/rockbox_flash.c
@@ -977,6 +977,7 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
{
char* filename;
bool show_greet;
+ int oldmode;
/* this macro should be called as the first thing you do in the plugin.
it test that the api version and model the plugin was compiled for
@@ -997,7 +998,9 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
rb = api; /* copy to global api pointer */
/* now go ahead and have fun! */
+ oldmode = rb->system_memory_guard(MEMGUARD_NONE); /*disable memory guard */
DoUserDialog(filename, show_greet);
+ rb->system_memory_guard(oldmode); /* re-enable memory guard */
return PLUGIN_OK;
}
diff --git a/firmware/export/system.h b/firmware/export/system.h
index 0d601e3d47..0c4a8f1a86 100644
--- a/firmware/export/system.h
+++ b/firmware/export/system.h
@@ -164,6 +164,17 @@ static inline int cas2 (volatile int *pointer1,volatile int *pointer2,int reques
set_irq_level(oldlevel);
return 0;
}
+
+/* Utilize the user break controller to catch invalid memory accesses. */
+int system_memory_guard(int newmode);
+
+enum {
+ MEMGUARD_KEEP = -1, /* don't change the mode; for reading */
+ MEMGUARD_NONE = 0, /* catch nothing */
+ MEMGUARD_FLASH_WRITES, /* catch writes to area 02 (flash ROM) */
+ MEMGUARD_ZERO_AREA, /* catch all accesses to areas 00 and 01 */
+ MAXMEMGUARD
+};
#endif
diff --git a/firmware/system.c b/firmware/system.c
index 33d5fbf74a..234e29433d 100644
--- a/firmware/system.c
+++ b/firmware/system.c
@@ -315,7 +315,7 @@ void system_reboot (void)
ICR = 0;
asm volatile ("jmp @%0; mov.l @%1,r15" : :
- "r"(*(int*)0),"r"(4));
+ "r"(*(int*)0),"r"(4));
}
void UIE (unsigned int pc) /* Unexpected Interrupt or Exception */
@@ -498,4 +498,50 @@ void system_init(void)
WCR1 = 0x4000; /* Long wait states for CS6 (ATA), short for the rest. */
WCR3 = 0x8000; /* WAIT is pulled up, 1 state inserted for CS6 */
#endif
+
+}
+
+/* Utilize the user break controller to catch invalid memory accesses. */
+int system_memory_guard(int newmode)
+{
+ static const struct {
+ unsigned long addr;
+ unsigned long mask;
+ unsigned short bbr;
+ } modes[MAXMEMGUARD] = {
+ /* catch nothing */
+ { 0x00000000, 0x00000000, 0x0000 },
+ /* catch writes to area 02 (flash ROM) */
+ { 0x02000000, 0x00FFFFFF, 0x00F8 },
+ /* catch all accesses to areas 00 (internal ROM) and 01 (free) */
+ { 0x00000000, 0x01FFFFFF, 0x00FC }
+ };
+
+ int oldmode = MEMGUARD_NONE;
+ int i;
+
+ /* figure out the old mode from what is in the UBC regs. If the register
+ values don't match any mode, assume MEMGUARD_NONE */
+ for (i = MEMGUARD_NONE; i < MAXMEMGUARD; i++)
+ {
+ if (BAR == modes[i].addr && BAMR == modes[i].mask &&
+ BBR == modes[i].bbr)
+ {
+ oldmode = i;
+ break;
+ }
+ }
+
+ if (newmode == MEMGUARD_KEEP)
+ newmode = oldmode;
+
+ BBR = 0; /* switch off everything first */
+
+ /* always set the UBC according to the mode, in case the old settings
+ didn't match any valid mode */
+ BAR = modes[newmode].addr;
+ BAMR = modes[newmode].mask;
+ BBR = modes[newmode].bbr;
+
+ return oldmode;
}