2007-02-23 09:30:09 +00:00
|
|
|
/***************************************************************************
|
|
|
|
* __________ __ ___.
|
|
|
|
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
|
|
|
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
|
|
|
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
|
|
|
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
|
|
|
* \/ \/ \/ \/ \/
|
|
|
|
* $Id$
|
|
|
|
*
|
|
|
|
* Copyright (C) 2006 by Greg White
|
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*
|
|
|
|
****************************************************************************/
|
2006-08-12 08:27:48 +00:00
|
|
|
#include "config.h"
|
|
|
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include "cpu.h"
|
|
|
|
#include "system.h"
|
|
|
|
#include "lcd.h"
|
|
|
|
#include "kernel.h"
|
|
|
|
#include "thread.h"
|
|
|
|
#include "ata.h"
|
|
|
|
#include "fat.h"
|
|
|
|
#include "disk.h"
|
|
|
|
#include "font.h"
|
|
|
|
#include "adc.h"
|
|
|
|
#include "backlight.h"
|
|
|
|
#include "panic.h"
|
|
|
|
#include "power.h"
|
|
|
|
#include "file.h"
|
2006-12-29 02:49:12 +00:00
|
|
|
#include "button-target.h"
|
2007-02-22 15:09:49 +00:00
|
|
|
#include "common.h"
|
2006-12-29 02:49:12 +00:00
|
|
|
|
2007-01-17 01:49:19 +00:00
|
|
|
extern void map_memory(void);
|
2006-12-29 02:49:12 +00:00
|
|
|
|
2006-08-12 08:27:48 +00:00
|
|
|
char version[] = APPSVERSION;
|
|
|
|
|
2007-01-17 01:49:19 +00:00
|
|
|
static void go_usb_mode(void)
|
2006-12-29 02:49:12 +00:00
|
|
|
{
|
2007-01-17 01:49:19 +00:00
|
|
|
/* Drop into USB mode. This does not check for disconnection. */
|
2006-08-12 08:27:48 +00:00
|
|
|
int i;
|
|
|
|
|
|
|
|
GPBDAT &= 0x7EF;
|
|
|
|
GPBCON |= 1<<8;
|
|
|
|
|
|
|
|
GPGDAT &= 0xE7FF;
|
|
|
|
GPGDAT |= 1<<11;
|
|
|
|
|
2007-01-17 01:49:19 +00:00
|
|
|
for(i = 0; i < 10000000; i++) {
|
|
|
|
continue;
|
|
|
|
}
|
2006-08-12 08:27:48 +00:00
|
|
|
|
|
|
|
GPBCON &= 0x2FFCFF;
|
2006-12-29 02:49:12 +00:00
|
|
|
GPBDAT |= 1<<5;
|
2006-08-12 08:27:48 +00:00
|
|
|
GPBDAT |= 1<<6;
|
|
|
|
}
|
|
|
|
|
2006-12-29 02:49:12 +00:00
|
|
|
|
|
|
|
/* Restores a factory kernel/bootloader from a known location */
|
|
|
|
/* Restores the FWIMG01.DAT file back in the case of a bootloader failure */
|
|
|
|
/* The factory or "good" bootloader must be in /GBSYSTEM/FWIMG/FWIMG01.DAT.ORIG */
|
|
|
|
/* Returns non-zero on failure */
|
|
|
|
int restore_fwimg01dat(void)
|
|
|
|
{
|
|
|
|
int orig_file = 0, dest_file = 0;
|
|
|
|
int size = 0, size_read;
|
2007-01-17 01:49:19 +00:00
|
|
|
static char buf[4096];
|
2007-02-22 15:09:49 +00:00
|
|
|
|
2006-12-29 02:49:12 +00:00
|
|
|
orig_file = open("/GBSYSTEM/FWIMG/FWIMG01.DAT.ORIG", O_RDONLY);
|
2007-01-17 01:49:19 +00:00
|
|
|
if(orig_file < 0) {
|
2006-12-29 02:49:12 +00:00
|
|
|
/* Couldn't open source file */
|
2007-02-22 15:09:49 +00:00
|
|
|
printf("Couldn't open FWIMG01.DAT.ORIG for reading");
|
2006-12-29 02:49:12 +00:00
|
|
|
return(1);
|
|
|
|
}
|
|
|
|
|
2007-02-22 15:09:49 +00:00
|
|
|
printf("FWIMG01.DAT.ORIG opened for reading");
|
2006-12-29 02:49:12 +00:00
|
|
|
|
|
|
|
dest_file = open("/GBSYSTEM/FWIMG/FWIMG01.DAT", O_RDWR);
|
2007-01-17 01:49:19 +00:00
|
|
|
if(dest_file < 0) {
|
2006-12-29 02:49:12 +00:00
|
|
|
/* Couldn't open destination file */
|
2007-02-22 15:09:49 +00:00
|
|
|
printf("Couldn't open FWIMG01.DAT.ORIG for writing");
|
2006-12-29 02:49:12 +00:00
|
|
|
close(orig_file);
|
|
|
|
return(2);
|
|
|
|
}
|
|
|
|
|
2007-02-22 15:09:49 +00:00
|
|
|
printf("FWIMG01.DAT opened for writing");
|
2006-12-29 02:49:12 +00:00
|
|
|
|
|
|
|
do {
|
|
|
|
/* Copy in chunks */
|
|
|
|
size_read = read(orig_file, buf, sizeof(buf));
|
2007-01-17 01:49:19 +00:00
|
|
|
if(size_read != write(dest_file, buf, size_read)) {
|
2006-12-29 02:49:12 +00:00
|
|
|
close(orig_file);
|
|
|
|
close(dest_file);
|
|
|
|
return(3);
|
|
|
|
}
|
|
|
|
size += size_read;
|
|
|
|
|
2007-01-17 01:49:19 +00:00
|
|
|
} while(size_read > 0);
|
2006-12-29 02:49:12 +00:00
|
|
|
|
|
|
|
close(orig_file);
|
|
|
|
close(dest_file);
|
|
|
|
|
2007-02-22 15:09:49 +00:00
|
|
|
printf("Finished copying %ld bytes from", size);
|
|
|
|
printf("FWIMG01.DAT.ORIG to FWIMG01.DAT");
|
2006-12-29 02:49:12 +00:00
|
|
|
|
|
|
|
return(0);
|
|
|
|
}
|
|
|
|
|
2007-01-17 18:31:40 +00:00
|
|
|
char buf[256];
|
|
|
|
|
|
|
|
void display_instructions(void)
|
|
|
|
{
|
|
|
|
lcd_setfont(FONT_SYSFIXED);
|
2007-02-22 15:09:49 +00:00
|
|
|
printf("Hold MENU when booting for rescue mode.");
|
|
|
|
printf(" \"VOL+\" button to restore original kernel");
|
|
|
|
printf(" \"A\" button to load original firmware");
|
|
|
|
printf("");
|
|
|
|
printf("FRAME %x TTB %x", FRAME, TTB_BASE);
|
2007-01-17 18:31:40 +00:00
|
|
|
}
|
2007-01-17 01:49:19 +00:00
|
|
|
|
2006-08-12 08:27:48 +00:00
|
|
|
void * main(void)
|
|
|
|
{
|
2006-12-29 02:49:12 +00:00
|
|
|
int i;
|
2006-08-12 08:27:48 +00:00
|
|
|
struct partinfo* pinfo;
|
|
|
|
unsigned short* identify_info;
|
2006-12-29 02:49:12 +00:00
|
|
|
unsigned char* loadbuffer;
|
|
|
|
int buffer_size;
|
|
|
|
bool load_original = false;
|
|
|
|
int rc;
|
|
|
|
int(*kernel_entry)(void);
|
2006-08-12 08:27:48 +00:00
|
|
|
|
2007-01-17 01:49:19 +00:00
|
|
|
bool show_bootsplash = true;
|
|
|
|
|
|
|
|
if(GPGDAT & 2)
|
|
|
|
show_bootsplash = false;
|
|
|
|
|
|
|
|
if(!show_bootsplash) {
|
2007-01-17 18:31:40 +00:00
|
|
|
lcd_init();
|
|
|
|
display_instructions();
|
2007-01-17 01:49:19 +00:00
|
|
|
sleep(2*HZ);
|
2007-01-17 18:31:40 +00:00
|
|
|
}
|
2007-01-17 01:49:19 +00:00
|
|
|
if(GPGDAT & 2) {
|
2007-01-17 18:31:40 +00:00
|
|
|
lcd_init();
|
2007-02-22 15:09:49 +00:00
|
|
|
printf("Entering rescue mode..");
|
2006-08-12 08:27:48 +00:00
|
|
|
go_usb_mode();
|
|
|
|
while(1);
|
|
|
|
}
|
2006-12-29 02:49:12 +00:00
|
|
|
if(GPGDAT & 0x10) {
|
2007-01-17 18:31:40 +00:00
|
|
|
lcd_init();
|
2006-12-29 02:49:12 +00:00
|
|
|
load_original = true;
|
2007-02-22 15:09:49 +00:00
|
|
|
printf("Loading original firmware...");
|
2007-01-17 01:49:19 +00:00
|
|
|
}
|
2006-12-29 02:49:12 +00:00
|
|
|
|
2006-08-12 08:27:48 +00:00
|
|
|
i = ata_init();
|
|
|
|
i = disk_mount_all();
|
2007-01-17 01:49:19 +00:00
|
|
|
if(!show_bootsplash) {
|
2007-02-22 15:09:49 +00:00
|
|
|
printf("disk_mount_all: %d", i);
|
2007-01-17 01:49:19 +00:00
|
|
|
}
|
2007-01-17 18:31:40 +00:00
|
|
|
if(show_bootsplash) {
|
|
|
|
int fd = open("/bootsplash.raw", O_RDONLY);
|
|
|
|
if(fd < 0) {
|
|
|
|
show_bootsplash = false;
|
|
|
|
lcd_init();
|
|
|
|
display_instructions();
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
read(fd, lcd_framebuffer, LCD_WIDTH*LCD_HEIGHT*2);
|
|
|
|
close(fd);
|
|
|
|
lcd_update();
|
|
|
|
lcd_init();
|
|
|
|
}
|
|
|
|
}
|
2006-12-29 02:49:12 +00:00
|
|
|
/* hold VOL+ to enter rescue mode to copy old image */
|
|
|
|
/* needs to be after ata_init and disk_mount_all */
|
2007-01-17 01:49:19 +00:00
|
|
|
if(GPGDAT & 4) {
|
2006-12-29 02:49:12 +00:00
|
|
|
|
|
|
|
/* Try to restore the original kernel/bootloader if a copy is found */
|
2007-02-22 15:09:49 +00:00
|
|
|
printf("Restoring FWIMG01.DAT...");
|
2006-12-29 02:49:12 +00:00
|
|
|
|
2007-01-17 01:49:19 +00:00
|
|
|
if(!restore_fwimg01dat()) {
|
2007-02-22 15:09:49 +00:00
|
|
|
printf("Restoring FWIMG01.DAT successful.");
|
2006-12-29 02:49:12 +00:00
|
|
|
} else {
|
2007-02-22 15:09:49 +00:00
|
|
|
printf("Restoring FWIMG01.DAT failed.");
|
2006-12-29 02:49:12 +00:00
|
|
|
}
|
|
|
|
|
2007-02-22 15:09:49 +00:00
|
|
|
printf("Now power cycle to boot original");
|
2006-12-29 02:49:12 +00:00
|
|
|
while(1);
|
|
|
|
}
|
|
|
|
|
2007-01-17 01:49:19 +00:00
|
|
|
if(!show_bootsplash) {
|
|
|
|
identify_info = ata_get_identify();
|
2006-08-12 08:27:48 +00:00
|
|
|
|
2007-01-17 01:49:19 +00:00
|
|
|
for(i=0; i < 20; i++)
|
|
|
|
((unsigned short*)buf)[i]=htobe16(identify_info[i+27]);
|
2006-08-12 08:27:48 +00:00
|
|
|
|
2007-01-17 01:49:19 +00:00
|
|
|
buf[40]=0;
|
2006-08-12 08:27:48 +00:00
|
|
|
|
2007-01-17 01:49:19 +00:00
|
|
|
/* kill trailing space */
|
|
|
|
for(i=39; i && buf[i]==' '; i--)
|
|
|
|
buf[i] = 0;
|
2006-08-12 08:27:48 +00:00
|
|
|
|
2007-02-22 15:09:49 +00:00
|
|
|
printf("Model");
|
|
|
|
printf(buf);
|
2006-08-12 08:27:48 +00:00
|
|
|
|
2007-01-17 01:49:19 +00:00
|
|
|
for(i=0; i < 4; i++)
|
|
|
|
((unsigned short*)buf)[i]=htobe16(identify_info[i+23]);
|
2006-08-12 08:27:48 +00:00
|
|
|
|
2007-01-17 01:49:19 +00:00
|
|
|
buf[8]=0;
|
2006-08-12 08:27:48 +00:00
|
|
|
|
2007-02-22 15:09:49 +00:00
|
|
|
printf("Firmware");
|
|
|
|
printf(buf);
|
2006-12-29 02:49:12 +00:00
|
|
|
|
2007-01-17 01:49:19 +00:00
|
|
|
pinfo = disk_partinfo(0);
|
2007-02-22 15:09:49 +00:00
|
|
|
printf("Partition 0: 0x%02x %ld MB", pinfo->type, pinfo->size / 2048);
|
2007-01-17 01:49:19 +00:00
|
|
|
}
|
2006-12-29 02:49:12 +00:00
|
|
|
/* Load original firmware */
|
|
|
|
if(load_original) {
|
|
|
|
loadbuffer = (unsigned char*)0x30008000;
|
|
|
|
buffer_size =(unsigned char*)0x31000000 - loadbuffer;
|
2007-02-22 21:19:48 +00:00
|
|
|
rc = load_raw_firmware(loadbuffer, "/rockbox.gigabeat", buffer_size);
|
2007-02-22 15:09:49 +00:00
|
|
|
if(rc < EOK) {
|
|
|
|
printf("Error!");
|
|
|
|
printf("Failed to load original firmware:");
|
|
|
|
printf(strerror(rc));
|
|
|
|
printf("Loading rockbox");
|
2006-12-29 02:49:12 +00:00
|
|
|
sleep(2*HZ);
|
|
|
|
goto load_rockbox;
|
|
|
|
}
|
2006-08-12 08:27:48 +00:00
|
|
|
|
2007-02-22 15:09:49 +00:00
|
|
|
printf("Loaded: %d", rc);
|
2006-12-29 02:49:12 +00:00
|
|
|
sleep(2*HZ);
|
|
|
|
|
|
|
|
(*((int*)0x7000000)) = 333;
|
|
|
|
rc = *((int*)0x7000000+0x8000000);
|
2007-02-22 15:09:49 +00:00
|
|
|
printf("Bank0 mem test: %d", rc);
|
2006-12-29 02:49:12 +00:00
|
|
|
sleep(3*HZ);
|
|
|
|
|
2007-02-22 15:09:49 +00:00
|
|
|
printf("Woops, should not return from firmware!");
|
2006-12-29 02:49:12 +00:00
|
|
|
goto usb;
|
|
|
|
}
|
2006-08-12 08:27:48 +00:00
|
|
|
|
2006-12-29 02:49:12 +00:00
|
|
|
load_rockbox:
|
|
|
|
map_memory();
|
2007-01-17 01:49:19 +00:00
|
|
|
if(!show_bootsplash) {
|
2007-02-22 15:09:49 +00:00
|
|
|
printf("Loading Rockbox...");
|
2007-01-17 01:49:19 +00:00
|
|
|
}
|
2006-12-29 02:49:12 +00:00
|
|
|
|
|
|
|
loadbuffer = (unsigned char*) 0x100;
|
|
|
|
buffer_size = (unsigned char*)0x400000 - loadbuffer;
|
2007-03-03 16:02:14 +00:00
|
|
|
rc = load_raw_firmware(loadbuffer, "/.rockbox/rockbox.gigabeat", buffer_size);
|
2007-02-22 15:09:49 +00:00
|
|
|
if(rc < EOK) {
|
2007-03-03 16:02:14 +00:00
|
|
|
rc = load_raw_firmware(loadbuffer, "/rockbox.gigabeat", buffer_size);
|
|
|
|
}
|
|
|
|
if(rc < EOK) {
|
|
|
|
printf("Error!");
|
|
|
|
printf("Can't load rockbox.gigabeat:");
|
|
|
|
printf(strerror(rc));
|
2006-12-29 02:49:12 +00:00
|
|
|
} else {
|
2007-01-17 01:49:19 +00:00
|
|
|
if(!show_bootsplash) {
|
2007-02-22 15:09:49 +00:00
|
|
|
printf("Rockbox loaded.");
|
2007-01-17 01:49:19 +00:00
|
|
|
}
|
2007-01-13 02:24:15 +00:00
|
|
|
kernel_entry = (void*) loadbuffer;
|
2006-12-29 02:49:12 +00:00
|
|
|
rc = kernel_entry();
|
2007-02-22 15:09:49 +00:00
|
|
|
printf("Woops, should not return from firmware: %d", rc);
|
2006-12-29 02:49:12 +00:00
|
|
|
goto usb;
|
|
|
|
}
|
|
|
|
usb:
|
2006-08-12 08:27:48 +00:00
|
|
|
/* now wait in USB mode so the bootloader can be updated */
|
|
|
|
go_usb_mode();
|
|
|
|
while(1);
|
|
|
|
|
2007-01-17 01:49:19 +00:00
|
|
|
return((void *)0);
|
2006-08-12 08:27:48 +00:00
|
|
|
}
|
|
|
|
|