1
0
Fork 0
forked from len0rd/rockbox

source code for all my flash stuff, now finally in cvs

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@4083 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Jörg Hohensohn 2003-11-30 11:37:43 +00:00
parent 014c4fa1f8
commit 6a4e4c87c2
29 changed files with 3349 additions and 1 deletions

View file

@ -1 +1,7 @@
Readme
(c) 2003 by Jörg Hohensohn
Sourcecode for the flash "infrastructure"
Please bear in mind that these are powerful tools, don't fool with them!
For most up-to-date info about flashing see:
http://rockbox.haxx.se/docs/flash.html

78
flash/bootloader/Makefile Normal file
View file

@ -0,0 +1,78 @@
# __________ __ ___.
# Open \______ \ ____ ____ | | _\_ |__ _______ ___
# Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
# Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
# Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
# \/ \/ \/ \/ \/
# $Id$
#
CC = sh-elf-gcc
LD = sh-elf-ld
AR = sh-elf-ar
AS = sh-elf-as
OC = sh-elf-objcopy
FIRMWARE := ../../firmware
TOOLSDIR=../../tools
TARGET = bootloader
LDS := $(TARGET).lds
ifndef PLATFORM
not_configured:
@echo "No platform given."
@echo "Use make PLATFORM=PLAYER|RECORDER|RECORDER|FM {NO_ROM=1}"
##else
##configured:
## @echo "Building bootloader for platform "$(PLATFORM)
endif
INCLUDES= -I$(FIRMWARE)/export -I. -I$(OBJDIR)
DEFINES= -DPLATFORM_$(PLATFORM)
OBJDIR := .
CFLAGS = -O -W -Wall -m1 -nostdlib -ffreestanding -Wstrict-prototypes -fomit-frame-pointer -fschedule-insns $(INCLUDES) $(DEFINES)
AFLAGS += -small -relax
ifdef DEBUG
DEFINES := -DDEBUG
CFLAGS += -g
endif
SRC := $(wildcard *.c)
OBJS := $(SRC:%.c=$(OBJDIR)/%.o)
ifdef NO_ROM
LINKFILE = $(OBJDIR)/no_rom.lds
ORIGIN = 0
DEFINES += -DNO_ROM
else
LINKFILE = $(OBJDIR)/$(TARGET).lds
ORIGIN = FFFF500
endif
$(OBJDIR)/$(TARGET).bin : $(OBJDIR)/$(TARGET).elf
$(OC) -O binary $(OBJDIR)/$(TARGET).elf $(OBJDIR)/$(TARGET).bin
$(TOOLSDIR)/sh2d $(OBJDIR)/$(TARGET).bin -o $(ORIGIN) > $(OBJDIR)/$(TARGET).asm
ifndef NO_ROM
$(TOOLSDIR)/scramble $(OBJDIR)/$(TARGET).bin $(OBJDIR)/$(TARGET).ajz
endif
$(OBJDIR)/$(TARGET).elf : $(OBJS)
$(CC) -Os -nostdlib -o $(OBJDIR)/$(TARGET).elf -L$(OBJDIR) -T$(LINKFILE) -Wl,-Map,$(OBJDIR)/$(TARGET).map
clean:
-rm -f \
$(OBJS) \
$(OBJDIR)/$(TARGET).asm \
$(OBJDIR)/$(TARGET).bin \
$(OBJDIR)/$(TARGET).ajz \
$(OBJDIR)/$(TARGET).elf \
$(OBJDIR)/$(TARGET).map

4
flash/bootloader/README Normal file
View file

@ -0,0 +1,4 @@
(c) 2003 by Jörg Hohensohn
This is the source code for the flash bootloader.
It give the dual boot feature, decompresses one of two software images.

View file

@ -0,0 +1,480 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2003 by Jörg Hohensohn
*
* Second-level bootloader, with dual-boot feature by holding F1/Menu
* This is the image being descrambled and executed by the boot ROM.
* It's task is to copy Rockbox from Flash to DRAM.
* The image(s) in flash may optionally be compressed with UCL 2e
*
* 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 "sh7034.h"
#include "bootloader.h"
#ifdef NO_ROM
// start with the vector table
UINT32 vectors[] __attribute__ ((section (".vectors"))) =
{
(UINT32)_main, // entry point, the copy routine
(UINT32)(end_stack - 1), // initial stack pointer
FLASH_BASE + 0x200, // source of image in flash
(UINT32)total_size, // size of image
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0x03020080 // mask and version (just as a suggestion)
};
#else
// our binary has to start with a vector to the entry point
tpMain start_vector[] __attribute__ ((section (".startvector"))) = {main};
#endif
#ifdef NO_ROM // some code which is only needed for the romless variant
void _main(void)
{
UINT32* pSrc;
UINT32* pDest;
UINT32* pEnd;
/*
asm volatile ("ldc %0,sr" : : "r"(0xF0)); // disable interrupts
asm volatile ("mov.l @%0,r15" : : "r"(4)); // load stack
asm volatile ("ldc %0,vbr" : : "r"(0)); // load vector base
*/
// copy everything to IRAM and continue there
pSrc = begin_iramcopy;
pDest = begin_text;
pEnd = pDest + (begin_stack - begin_text);
do
{
*pDest++ = *pSrc++;
}
while (pDest < pEnd);
main(); // jump to the real main()
}
void BootInit(void)
{
// inits from the boot ROM, whether they make sense or not
PBDR &= 0xFFBF; // LED off (0x131E)
PBCR2 = 0; // all GPIO
PBIOR |= 0x40; // LED output
PBIOR &= 0xFFF1; // LCD lines input
// init DRAM like the boot ROM does
PACR2 &= 0xFFFB;
PACR2 |= 0x0008;
CASCR = 0xAF;
BCR |= 0x8000;
WCR1 &= 0xFDFD;
DCR = 0x0E00;
RCR = 0x5AB0;
RTCOR = 0x9605;
RTCSR = 0xA518;
}
#endif // #ifdef NO_ROM
int main(void)
{
int nButton;
PlatformInit(); // model-specific inits
nButton = ButtonPressed();
if (nButton == 3)
{ // F3 means start monitor
MiniMon();
}
else
{
tImage* pImage;
pImage = GetStartImage(nButton); // which image
DecompressStart(pImage); // move into place and start it
}
return 0; // I guess we won't return ;-)
}
// init code that is specific to certain platform
void PlatformInit(void)
{
#ifdef NO_ROM
BootInit(); // if not started by boot ROM, we need to init what it did
#endif
#if defined PLATFORM_PLAYER
BRR1 = 0x0019; // 14400 Baud for monitor
if (FW_VERSION > 451) // "new" Player?
{
PBDR &= ~0x10; // set PB4 to 0 to power-up the harddisk early
PBIOR |= 0x10; // make PB4 an output
}
#elif defined PLATFORM_RECORDER
BRR1 = 0x0002; // 115200 Baud for monitor
if (ReadADC(7) > 0x100) // charger plugged?
{ // switch off the HD, else a flat battery may not start
PACR2 &= 0xFBFF; // GPIO for PA5
PAIOR |= 0x20; // make PA5 an output (low by default)
}
#elif defined PLATFORM_FM
BRR1 = 0x0002; // 115200 Baud for monitor
PBDR |= 0x20; // set PB5 to keep power (fixes the ON-holding problem)
PBIOR |= 0x20; // make PB5 an output
if (ReadADC(0) < 0x1FF) // charger plugged?
{
// how do we switch this off?
}
#endif
// platform-independent inits
DCR |= 0x1000; // enable burst mode on DRAM
BCR |= 0x2000; // activate Warp mode (simultaneous internal and external mem access)
}
// Thinned out version of the UCL 2e decompression sourcecode
// Original (C) Markus F.X.J Oberhumer under GNU GPL license
#define GETBIT(bb, src, ilen) \
(((bb = bb & 0x7f ? bb*2 : ((unsigned)src[ilen++]*2+1)) >> 8) & 1)
int ucl_nrv2e_decompress_8(
const UINT8 *src, UINT8 *dst, UINT32* dst_len)
{
UINT32 bb = 0;
unsigned ilen = 0, olen = 0, last_m_off = 1;
for (;;)
{
unsigned m_off, m_len;
while (GETBIT(bb,src,ilen))
{
dst[olen++] = src[ilen++];
}
m_off = 1;
for (;;)
{
m_off = m_off*2 + GETBIT(bb,src,ilen);
if (GETBIT(bb,src,ilen)) break;
m_off = (m_off-1)*2 + GETBIT(bb,src,ilen);
}
if (m_off == 2)
{
m_off = last_m_off;
m_len = GETBIT(bb,src,ilen);
}
else
{
m_off = (m_off-3)*256 + src[ilen++];
if (m_off == 0xffffffff)
break;
m_len = (m_off ^ 0xffffffff) & 1;
m_off >>= 1;
last_m_off = ++m_off;
}
if (m_len)
m_len = 1 + GETBIT(bb,src,ilen);
else if (GETBIT(bb,src,ilen))
m_len = 3 + GETBIT(bb,src,ilen);
else
{
m_len++;
do {
m_len = m_len*2 + GETBIT(bb,src,ilen);
} while (!GETBIT(bb,src,ilen));
m_len += 3;
}
m_len += (m_off > 0x500);
{
const UINT8 *m_pos;
m_pos = dst + olen - m_off;
dst[olen++] = *m_pos++;
do dst[olen++] = *m_pos++; while (--m_len > 0);
}
}
*dst_len = olen;
return ilen;
}
// move the image into place and start it
void DecompressStart(tImage* pImage)
{
UINT32* pSrc;
UINT32* pDest;
pSrc = pImage->image;
pDest = pImage->pDestination;
if (pSrc != pDest) // if not linked to that flash address
{
if (pImage->flags & IF_UCL_2E)
{ // UCL compressed, algorithm 2e
UINT32 dst_len; // dummy
ucl_nrv2e_decompress_8((UINT8*)pSrc, (UINT8*)pDest, &dst_len);
}
else
{ // uncompressed, copy it
UINT32 size = pImage->size;
UINT32* pEnd;
size = (size + 3) / 4; // round up to 32bit-words
pEnd = pDest + size;
do
{
*pDest++ = *pSrc++;
}
while (pDest < pEnd);
}
}
pImage->pExecute();
}
int ReadADC(int channel)
{
// after channel 3, the ports wrap and get re-used
volatile UINT16* pResult = (UINT16*)(ADDRAH_ADDR + 2 * (channel & 0x03));
int timeout = 266; // conversion takes 266 clock cycles
ADCSR = 0x20 | channel; // start single conversion
while (((ADCSR & 0x80) == 0) && (--timeout)); // 6 instructions per round
return (timeout == 0) ? -1 : *pResult>>6;
}
// This function is platform-dependent,
// until I figure out how to distinguish at runtime.
int ButtonPressed(void) // return 1,2,3 for F1,F2,F3, 0 if none pressed
{
int value = ReadADC(CHANNEL);
if (value >= F1_LOWER && value <= F1_UPPER) // in range
return 1;
else if (value >= F2_LOWER && value <= F2_UPPER) // in range
return 2;
else if (value >= F3_LOWER && value <= F3_UPPER) // in range
return 3;
return 0;
}
// Determine the image to be started
tImage* GetStartImage(int nPreferred)
{
tImage* pImage1;
tImage* pImage2 = NULL; // default to not present
UINT32 pos;
UINT32* pFlash = (UINT32*)FLASH_BASE;
// determine the first image position
pos = pFlash[2] + pFlash[3]; // position + size of the bootloader = after it
pos = (pos + 3) & ~3; // be shure it's 32 bit aligned
pImage1 = (tImage*)pos;
if (pImage1->size != 0)
{ // check for second image
pos = (UINT32)(&pImage1->image) + pImage1->size;
pImage2 = (tImage*)pos;
// does it make sense? (not in FF or 00 erazed space)
if (pImage2->pDestination == (void*)0xFFFFFFFF
|| pImage2->size == 0xFFFFFFFF
|| pImage2->pExecute == (void*)0xFFFFFFFF
|| pImage2->flags == 0xFFFFFFFF
|| pImage2->pDestination == NULL) // size, execute and flags can legally be 0
{
pImage2 = NULL; // invalidate
}
}
if (pImage2 == NULL || nPreferred == 1)
{ // no second image or overridden: return the first
return pImage1;
}
return pImage2; // return second image
}
// diagnostic functions
void SetLed(BOOL bOn)
{
if (bOn)
PBDR |= 0x40;
else
PBDR &= ~0x40;
}
void UartInit(void)
{
PBIOR &= 0xFBFF; // input: RXD1 remote pin
PBCR1 |= 0x00A0; // set PB3+PB2 to UART
PBCR1 &= 0xFFAF; // clear bits 6, 4 -> UART
SMR1 = 0x0000; // async format 8N1, baud generator input is CPU clock
SCR1 = 0x0030; // transmit+receive enable
PBCR1 &= 0x00FF; // set bit 12...15 as GPIO
SSR1 &= 0x00BF; // clear bit 6 (RDRF, receive data register full)
}
UINT8 UartRead(void)
{
UINT8 byte;
while (!(SSR1 & SCI_RDRF)); // wait for char to be available
byte = RDR1;
SSR1 &= ~SCI_RDRF;
return byte;
}
void UartWrite(UINT8 byte)
{
while (!(SSR1 & SCI_TDRE)); // wait for transmit buffer empty
TDR1 = byte;
SSR1 &= ~SCI_TDRE;
}
// include the mini monitor as a rescue feature, started with F3
void MiniMon(void)
{
UINT8 cmd;
UINT32 addr;
UINT32 size;
UINT32 content;
volatile UINT8* paddr = NULL;
volatile UINT8* pflash = NULL; // flash base address
UartInit();
while (1)
{
cmd = UartRead();
switch (cmd)
{
case BAUDRATE:
content = UartRead();
UartWrite(cmd); // acknowledge by returning the command value
while (!(SSR1 & SCI_TEND)); // wait for empty shift register, before changing baudrate
BRR1 = content;
break;
case ADDRESS:
addr = (UartRead() << 24) | (UartRead() << 16) | (UartRead() << 8) | UartRead();
paddr = (UINT8*)addr;
pflash = (UINT8*)(addr & 0xFFF80000); // round down to 512k align
UartWrite(cmd); // acknowledge by returning the command value
break;
case BYTE_READ:
content = *paddr++;
UartWrite(content); // the content is the ack
break;
case BYTE_WRITE:
content = UartRead();
*paddr++ = content;
UartWrite(cmd); // acknowledge by returning the command value
break;
case BYTE_READ16:
size = 16;
while (size--)
{
content = *paddr++;
UartWrite(content); // the content is the ack
}
break;
case BYTE_WRITE16:
size = 16;
while (size--)
{
content = UartRead();
*paddr++ = content;
}
UartWrite(cmd); // acknowledge by returning the command value
break;
case BYTE_FLASH:
content = UartRead();
pflash[0x5555] = 0xAA; // set flash to command mode
pflash[0x2AAA] = 0x55;
pflash[0x5555] = 0xA0; // byte program command
*paddr++ = content;
UartWrite(cmd); // acknowledge by returning the command value
break;
case BYTE_FLASH16:
size = 16;
while (size--)
{
content = UartRead();
pflash[0x5555] = 0xAA; // set flash to command mode
pflash[0x2AAA] = 0x55;
pflash[0x5555] = 0xA0; // byte program command
*paddr++ = content;
}
UartWrite(cmd); // acknowledge by returning the command value
break;
case HALFWORD_READ:
content = *(UINT16*)paddr;
paddr += 2;
UartWrite(content >> 8); // highbyte
UartWrite(content & 0xFF); // lowbyte
break;
case HALFWORD_WRITE:
content = UartRead() << 8 | UartRead();
*(UINT16*)paddr = content;
paddr += 2;
UartWrite(cmd); // acknowledge by returning the command value
break;
case EXECUTE:
{
tpFunc pFunc = (tpFunc)paddr;
pFunc();
UartWrite(cmd); // acknowledge by returning the command value
}
break;
case VERSION:
UartWrite(1); // return our version number
break;
default:
{
SetLed(TRUE);
UartWrite(~cmd); // error acknowledge
}
} // case
} // while (1)
}

View file

@ -0,0 +1,111 @@
#ifndef NULL
#define NULL ((void*)0)
#endif
#define TRUE 1
#define FALSE 0
// scalar types
typedef unsigned char UINT8;
typedef unsigned short UINT16;
typedef unsigned long UINT32;
typedef int BOOL;
typedef void(*tpFunc)(void); // type for execute
typedef int(*tpMain)(void); // type for start vector to main()
// structure of an image in the flash
typedef struct
{
UINT32* pDestination; // address to copy it to
UINT32 size; // how many bytes of payload (to the next header)
tpFunc pExecute; // entry point
UINT32 flags; // uncompressed or compressed
// end of header, now comes the payload
UINT32 image[]; // the binary image starts here
// after the payload, the next header may follow, all 0xFF if none
} tImage;
// flags valid for image header
#define IF_NONE 0x00000000
#define IF_UCL_2E 0x00000001 // image is compressed with UCL, algorithm 2e
// resolve platform dependency of F1 button check
#if defined PLATFORM_PLAYER
#define CHANNEL 1
#define F1_LOWER 0 // this is the "Menu" key
#define F1_UPPER 384
#define F2_LOWER 1024 // not present
#define F2_UPPER 1024
#define F3_LOWER 1024
#define F3_UPPER 1024
#elif defined PLATFORM_RECORDER
#define CHANNEL 4
#define F1_LOWER 250
#define F1_UPPER 499
#define F2_LOWER 500
#define F2_UPPER 699
#define F3_LOWER 900
#define F3_UPPER 1023
#elif defined PLATFORM_FM
#define CHANNEL 4
#define F1_LOWER 150
#define F1_UPPER 384
#define F2_LOWER 385
#define F2_UPPER 544
#define F3_LOWER 700
#define F3_UPPER 1023
#else
#error ("No platform given!")
#endif
#define FLASH_BASE 0x02000000 // start of the flash memory
#define FW_VERSION *(unsigned short*)(FLASH_BASE + 0xFE) // firmware version
// prototypes
void _main(void) __attribute__ ((section (".startup")));
int main(void);
void PlatformInit(void);
void DramInit(void);
int ucl_nrv2e_decompress_8(const UINT8 *src, UINT8 *dst, UINT32* dst_len);
void DecompressStart(tImage* pImage);
int ReadADC(int channel);
int ButtonPressed(void);
tImage* GetStartImage(int nPreferred);
// test functions
void SetLed(BOOL bOn);
void UartInit(void);
UINT8 UartRead(void);
void UartWrite(UINT8 byte);
void MiniMon(void);
// minimon commands
#define BAUDRATE 0x00 // followed by BRR value; response: command byte
#define ADDRESS 0x01 // followed by 4 bytes address; response: command byte
#define BYTE_READ 0x02 // response: 1 byte content
#define BYTE_WRITE 0x03 // followed by 1 byte content; response: command byte
#define BYTE_READ16 0x04 // response: 16 bytes content
#define BYTE_WRITE16 0x05 // followed by 16 bytes; response: command byte
#define BYTE_FLASH 0x06 // followed by 1 byte content; response: command byte
#define BYTE_FLASH16 0x07 // followed by 16 bytes; response: command byte
#define HALFWORD_READ 0x08 // response: 2 byte content
#define HALFWORD_WRITE 0x09 // followed by 2 byte content; response: command byte
#define EXECUTE 0x0A // response: command byte if call returns
#define VERSION 0x0B // response: version
// linker symbols
extern UINT32 begin_text[];
extern UINT32 end_text[];
extern UINT32 begin_data[];
extern UINT32 end_data[];
extern UINT32 begin_bss[];
extern UINT32 end_bss[];
extern UINT32 begin_stack[];
extern UINT32 end_stack[];
extern UINT32 begin_iramcopy[];
extern UINT32 total_size[];

View file

@ -0,0 +1,34 @@
OUTPUT_FORMAT(elf32-sh)
INPUT(bootloader.o)
MEMORY
{
/* the boot ROM uses IRAM at 400-430, stay away and start at 500 */
IRAM : ORIGIN = 0x0FFFF500, LENGTH = 0xA00
/* and leave some room for stack at the end */
}
SECTIONS
{
.startvector :
{
*(.startvector)
. = ALIGN(0x4);
} > IRAM
.text :
{
*(.text)
. = ALIGN(0x4);
} > IRAM
.data :
{
*(.data)
} > IRAM
.bss :
{
*(.bss)
} > IRAM
}

View file

@ -0,0 +1,62 @@
/* This is for the variant without boot ROM,
where the flash ROM is mirrored to address zero */
OUTPUT_FORMAT(elf32-sh)
INPUT(bootloader.o)
MEMORY
{
IRAM : ORIGIN = 0x0FFFF000, LENGTH = 0x1000
FLASH : ORIGIN = 0x00000000, LENGTH = 0x40000
}
SECTIONS
{
.vectors :
{
*(.vectors)
. = ALIGN(0x200);
} > FLASH
.startup :
{
*(.startup)
. = ALIGN(0x4);
_begin_iramcopy = .;
} > FLASH
.text : AT ( _begin_iramcopy )
{
_begin_text = .;
*(.text)
. = ALIGN(0x4);
_end_text = .;
} > IRAM
.data : AT ( _end_text )
{
_begin_data = .;
*(.data)
. = ALIGN(0x4);
_end_data = .;
} > IRAM
.bss : AT ( _end_data )
{
_begin_bss = .;
*(.bss)
. = ALIGN(0x4);
_end_bss = .;
} > IRAM
.stack :
{
_begin_stack = .;
*(.stack)
. = ALIGN(0x1000);
_end_stack = .;
} > IRAM
/* size of the program (without vectors) */
_total_size = SIZEOF(.startup) + SIZEOF(.text) + SIZEOF(.data);
}

5
flash/extract/README Normal file
View file

@ -0,0 +1,5 @@
(c) 2003 by Jörg Hohensohn
This tool extracts the firmware image out of an original Archos ROM dump,
like created with the Rockbox debug->dump feature.
The extracted image can then be used to compose a dual-boot firmware.

140
flash/extract/extract.c Normal file
View file

@ -0,0 +1,140 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2003 by Jörg Hohensohn
*
* Tool to extract the scrambled image out of an Archos flash ROM dump
*
* 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 <stdio.h>
#include <stdlib.h>
#include <memory.h>
#define UINT8 unsigned char
#define UINT16 unsigned short
#define UINT32 unsigned long
#define IMAGE_HEADER 0x6000 // a 32 byte header in front of the software image
#define IMAGE_START 0x6020 // software image position in Flash
// place a 32 bit value into memory, big endian
void Write32(UINT8* pByte, UINT32 value)
{
pByte[0] = (UINT8)(value >> 24);
pByte[1] = (UINT8)(value >> 16);
pByte[2] = (UINT8)(value >> 8);
pByte[3] = (UINT8)(value);
}
// read a 32 bit value from memory, big endian
UINT32 Read32(UINT8* pByte)
{
UINT32 value = 0;
value |= (UINT32)pByte[0] << 24;
value |= (UINT32)pByte[1] << 16;
value |= (UINT32)pByte[2] << 8;
value |= (UINT32)pByte[3];
return value;
}
// entry point
int main(int argc, char* argv[])
{
FILE* pInFile;
FILE* pOutFile;
UINT8 aHeader[6];
UINT8 aImage[256*1024];
UINT32 i;
UINT32 uiSize, uiStart;
UINT16 usChecksum = 0;
if (argc < 2)
{
printf("Extract the software image out of an original Archos Flash ROM dump.\n");
printf("Result is a scrambled file, use the descramble tool to get the binary,\n");
printf(" always without the -fm option, even if processing an FM software.\n\n");
printf("Usage: extract <flash dump file> <output file>\n");
printf("Example: extract internal_rom_2000000-203FFFF.bin archos.ajz\n");
exit(0);
}
pInFile = fopen(argv[1], "rb");
if (pInFile == NULL)
{
printf("Error opening input file %s\n", argv[1]);
exit(1);
}
if (fread(aImage, 1, sizeof(aImage), pInFile) != sizeof(aImage))
{
printf("Error reading input file %s, must be 256kB in size.\n", argv[1]);
fclose(pInFile);
exit(2);
}
fclose(pInFile);
// find out about the type
uiStart = Read32(aImage + 8);
uiSize = Read32(aImage + 12); // booted ROM image
if (uiStart == 0x02000100 && uiSize > 20000)
{ // Player has no loader, starts directly with the image
uiStart = 0x0100;
}
else
{ // Recorder / FM / V2 Recorder
uiStart = IMAGE_START;
uiSize = Read32(aImage + IMAGE_HEADER + 4); // size record of header
}
// sanity check
if (uiSize > sizeof(aImage) - uiStart || uiSize < 40000)
{
printf("Error: Impossible image size &d bytes.\n", uiSize);
exit(3);
}
// generate checksum
for (i=0; i<uiSize; i++)
usChecksum += aImage[uiStart + i];
// make header
Write32(aHeader + 2, usChecksum); // checksum in 5th and 6th byte
Write32(aHeader, uiSize); // size in first 4 bytes
pOutFile = fopen(argv[2], "wb");
if (pOutFile == NULL)
{
printf("Error opening output file %s\n", argv[2]);
exit(4);
}
if (fwrite(aHeader, 1, sizeof(aHeader), pOutFile) != sizeof(aHeader)
|| fwrite(aImage + uiStart, 1, uiSize, pOutFile) != uiSize)
{
printf("Write error\n");
fclose(pOutFile);
exit(5);
}
fclose(pOutFile);
return 0;
}

100
flash/extract/extract.dsp Normal file
View file

@ -0,0 +1,100 @@
# Microsoft Developer Studio Project File - Name="extract" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Console Application" 0x0103
CFG=extract - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE NMAKE /f "extract.mak".
!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "extract.mak" CFG="extract - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "extract - Win32 Release" (based on "Win32 (x86) Console Application")
!MESSAGE "extract - Win32 Debug" (based on "Win32 (x86) Console Application")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
RSC=rc.exe
!IF "$(CFG)" == "extract - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release"
# PROP BASE Intermediate_Dir "Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release"
# PROP Intermediate_Dir "Release"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
# ADD BASE RSC /l 0x407 /d "NDEBUG"
# ADD RSC /l 0x407 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
!ELSEIF "$(CFG)" == "extract - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug"
# PROP BASE Intermediate_Dir "Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug"
# PROP Intermediate_Dir "Debug"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
# ADD BASE RSC /l 0x407 /d "_DEBUG"
# ADD RSC /l 0x407 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
!ENDIF
# Begin Target
# Name "extract - Win32 Release"
# Name "extract - Win32 Debug"
# Begin Group "Source Files"
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File
SOURCE=.\extract.c
# End Source File
# End Group
# Begin Group "Header Files"
# PROP Default_Filter "h;hpp;hxx;hm;inl"
# End Group
# Begin Group "Resource Files"
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
# End Group
# End Target
# End Project

View file

@ -0,0 +1,14 @@
(c) 2003 by Jörg Hohensohn
This tool composes a firmware file, out of:
1. Template for the first Flash page
2. Bootloader
3. Archos image
4. Rockbox image
Use with extreme caution, the components have to match!
The aspects are:
- Model (Player, Recorder, FM, V2)
- boot type (standard boot ROM or ROMless)
Such a firmware file can then be programmed with "firmware_flash.rock".

View file

@ -0,0 +1,338 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2003 by Jörg Hohensohn
*
* Autoring tool for the firmware image to be programmed into Flash ROM
* It composes the flash content with header, bootloader and image(s)
*
* 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 <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <string.h>
#define UINT8 unsigned char
#define UINT16 unsigned short
#define UINT32 unsigned long
#define BOOL int
#define TRUE 1
#define FALSE 0
// size of one flash sector, the granularity with which it can be erased
#define SECTORSIZE 4096
#define BOOTLOAD_DEST 0x0FFFF500 // for the "normal" one
#define BOOTLOAD_SCR 0x02000100
#define ROCKBOX_DEST 0x09000000
#define ROCKBOX_EXEC 0x09000200
// place a 32 bit value into memory, big endian
void Write32(UINT8* pByte, UINT32 value)
{
pByte[0] = (UINT8)(value >> 24);
pByte[1] = (UINT8)(value >> 16);
pByte[2] = (UINT8)(value >> 8);
pByte[3] = (UINT8)(value);
}
// read a 32 bit value from memory, big endian
UINT32 Read32(UINT8* pByte)
{
UINT32 value = 0;
value |= (UINT32)pByte[0] << 24;
value |= (UINT32)pByte[1] << 16;
value |= (UINT32)pByte[2] << 8;
value |= (UINT32)pByte[3];
return value;
}
UINT32 CalcCRC32 (const UINT8* buf, UINT32 len)
{
static const UINT32 crc_table[256] =
{ // CRC32 lookup table for polynomial 0x04C11DB7
0x00000000, 0x04C11DB7, 0x09823B6E, 0x0D4326D9, 0x130476DC, 0x17C56B6B,
0x1A864DB2, 0x1E475005, 0x2608EDB8, 0x22C9F00F, 0x2F8AD6D6, 0x2B4BCB61,
0x350C9B64, 0x31CD86D3, 0x3C8EA00A, 0x384FBDBD, 0x4C11DB70, 0x48D0C6C7,
0x4593E01E, 0x4152FDA9, 0x5F15ADAC, 0x5BD4B01B, 0x569796C2, 0x52568B75,
0x6A1936C8, 0x6ED82B7F, 0x639B0DA6, 0x675A1011, 0x791D4014, 0x7DDC5DA3,
0x709F7B7A, 0x745E66CD, 0x9823B6E0, 0x9CE2AB57, 0x91A18D8E, 0x95609039,
0x8B27C03C, 0x8FE6DD8B, 0x82A5FB52, 0x8664E6E5, 0xBE2B5B58, 0xBAEA46EF,
0xB7A96036, 0xB3687D81, 0xAD2F2D84, 0xA9EE3033, 0xA4AD16EA, 0xA06C0B5D,
0xD4326D90, 0xD0F37027, 0xDDB056FE, 0xD9714B49, 0xC7361B4C, 0xC3F706FB,
0xCEB42022, 0xCA753D95, 0xF23A8028, 0xF6FB9D9F, 0xFBB8BB46, 0xFF79A6F1,
0xE13EF6F4, 0xE5FFEB43, 0xE8BCCD9A, 0xEC7DD02D, 0x34867077, 0x30476DC0,
0x3D044B19, 0x39C556AE, 0x278206AB, 0x23431B1C, 0x2E003DC5, 0x2AC12072,
0x128E9DCF, 0x164F8078, 0x1B0CA6A1, 0x1FCDBB16, 0x018AEB13, 0x054BF6A4,
0x0808D07D, 0x0CC9CDCA, 0x7897AB07, 0x7C56B6B0, 0x71159069, 0x75D48DDE,
0x6B93DDDB, 0x6F52C06C, 0x6211E6B5, 0x66D0FB02, 0x5E9F46BF, 0x5A5E5B08,
0x571D7DD1, 0x53DC6066, 0x4D9B3063, 0x495A2DD4, 0x44190B0D, 0x40D816BA,
0xACA5C697, 0xA864DB20, 0xA527FDF9, 0xA1E6E04E, 0xBFA1B04B, 0xBB60ADFC,
0xB6238B25, 0xB2E29692, 0x8AAD2B2F, 0x8E6C3698, 0x832F1041, 0x87EE0DF6,
0x99A95DF3, 0x9D684044, 0x902B669D, 0x94EA7B2A, 0xE0B41DE7, 0xE4750050,
0xE9362689, 0xEDF73B3E, 0xF3B06B3B, 0xF771768C, 0xFA325055, 0xFEF34DE2,
0xC6BCF05F, 0xC27DEDE8, 0xCF3ECB31, 0xCBFFD686, 0xD5B88683, 0xD1799B34,
0xDC3ABDED, 0xD8FBA05A, 0x690CE0EE, 0x6DCDFD59, 0x608EDB80, 0x644FC637,
0x7A089632, 0x7EC98B85, 0x738AAD5C, 0x774BB0EB, 0x4F040D56, 0x4BC510E1,
0x46863638, 0x42472B8F, 0x5C007B8A, 0x58C1663D, 0x558240E4, 0x51435D53,
0x251D3B9E, 0x21DC2629, 0x2C9F00F0, 0x285E1D47, 0x36194D42, 0x32D850F5,
0x3F9B762C, 0x3B5A6B9B, 0x0315D626, 0x07D4CB91, 0x0A97ED48, 0x0E56F0FF,
0x1011A0FA, 0x14D0BD4D, 0x19939B94, 0x1D528623, 0xF12F560E, 0xF5EE4BB9,
0xF8AD6D60, 0xFC6C70D7, 0xE22B20D2, 0xE6EA3D65, 0xEBA91BBC, 0xEF68060B,
0xD727BBB6, 0xD3E6A601, 0xDEA580D8, 0xDA649D6F, 0xC423CD6A, 0xC0E2D0DD,
0xCDA1F604, 0xC960EBB3, 0xBD3E8D7E, 0xB9FF90C9, 0xB4BCB610, 0xB07DABA7,
0xAE3AFBA2, 0xAAFBE615, 0xA7B8C0CC, 0xA379DD7B, 0x9B3660C6, 0x9FF77D71,
0x92B45BA8, 0x9675461F, 0x8832161A, 0x8CF30BAD, 0x81B02D74, 0x857130C3,
0x5D8A9099, 0x594B8D2E, 0x5408ABF7, 0x50C9B640, 0x4E8EE645, 0x4A4FFBF2,
0x470CDD2B, 0x43CDC09C, 0x7B827D21, 0x7F436096, 0x7200464F, 0x76C15BF8,
0x68860BFD, 0x6C47164A, 0x61043093, 0x65C52D24, 0x119B4BE9, 0x155A565E,
0x18197087, 0x1CD86D30, 0x029F3D35, 0x065E2082, 0x0B1D065B, 0x0FDC1BEC,
0x3793A651, 0x3352BBE6, 0x3E119D3F, 0x3AD08088, 0x2497D08D, 0x2056CD3A,
0x2D15EBE3, 0x29D4F654, 0xC5A92679, 0xC1683BCE, 0xCC2B1D17, 0xC8EA00A0,
0xD6AD50A5, 0xD26C4D12, 0xDF2F6BCB, 0xDBEE767C, 0xE3A1CBC1, 0xE760D676,
0xEA23F0AF, 0xEEE2ED18, 0xF0A5BD1D, 0xF464A0AA, 0xF9278673, 0xFDE69BC4,
0x89B8FD09, 0x8D79E0BE, 0x803AC667, 0x84FBDBD0, 0x9ABC8BD5, 0x9E7D9662,
0x933EB0BB, 0x97FFAD0C, 0xAFB010B1, 0xAB710D06, 0xA6322BDF, 0xA2F33668,
0xBCB4666D, 0xB8757BDA, 0xB5365D03, 0xB1F740B4
};
UINT32 i;
UINT32 crc = 0xffffffff;
for (i = 0; i < len; i++)
crc = (crc << 8) ^ crc_table[((crc >> 24) ^ *buf++) & 0xFF];
return crc;
}
UINT32 PlaceImage(char* filename, UINT32 pos, UINT8* pFirmware, UINT32 limit)
{
UINT32 size, read;
FILE* pFile;
UINT32 align;
UINT32 flags;
// magic file header for compressed files
static const UINT8 magic[8] = { 0x00,0xe9,0x55,0x43,0x4c,0xff,0x01,0x1a };
UINT8 ucl_header[26];
pFile = fopen(filename, "rb"); // open the current image
if (pFile == NULL)
{
printf("Image file %s not found!\n", filename);
exit(5);
}
fseek(pFile, 0, SEEK_END);
size = ftell(pFile);
fseek(pFile, 0, SEEK_SET);
// determine if compressed
flags = 0x00000000; // default: flags for uncompressed
fread(ucl_header, 1, sizeof(ucl_header), pFile);
if (memcmp(magic, ucl_header, sizeof(magic)) == 0)
{
if (ucl_header[12] != 0x2E) // check algorithm
{
printf("UCL compressed files must use algorithm 2e, not %d\n", ucl_header[12]);
printf("Generate with: uclpack --best --2e rockbox.bin %s\n", filename);
exit(6);
}
size = Read32(ucl_header + 22); // compressed size
if (Read32(ucl_header + 18) > size) // compare with uncompressed size
{ // normal case
flags = 0x00000001; // flags for UCL compressed
}
}
else
{
fseek(pFile, 0, SEEK_SET); // go back
}
if (pos + 16 + size > limit) // enough space for all that?
{
printf("Exceeding maximum image size %d\n", limit);
exit(7);
}
// write header
align = (pos + 16 + size + SECTORSIZE-1) & ~(SECTORSIZE-1); // round up to next flash sector
Write32(pFirmware + pos, ROCKBOX_DEST); // load address
Write32(pFirmware + pos + 4, align - (pos + 16)); // image size
Write32(pFirmware + pos + 8, ROCKBOX_EXEC); // execution address
Write32(pFirmware + pos + 12, flags); // compressed or not
pos += 16;
// load image
read = fread(pFirmware + pos, 1, size, pFile);
if (read != size)
{
printf("Read error, expecting %d bytes, got only %d\n", size, read);
exit(8);
}
fclose (pFile);
pos += size;
return pos;
}
int main(int argc, char* argv[])
{
static UINT8 aFirmware[512*1024]; // maximum with exchanged chip
FILE* pFile;
UINT32 size; // size of loaded item
UINT32 pos; // current position in firmware
UINT32 crc32; // checksum of "payload"
BOOL hasBootRom; // flag if regular boot ROM or directly starts from flash
UINT32 template_F8, template_FC; // my platform ID, mask and version
int i;
if (argc <= 4)
{
printf("Usage:\n");
printf("make_firmware <output> <template.bin> <bootloader.ajz> <image1.ucl> {image2.ucl}\n");
printf("<template.bin> is the original firmware from your box\n");
printf("<bootloader.ajz> is the scrambled bootloader\n");
printf("<image1.ucl> is the first image, compressed (recommended) or uncompressed\n");
printf("<image1.ucl> is the second image, compressed (recommended) or uncompressed\n");
printf("More images may follow, but keep the flash size in mind!\n");
printf("Compression must be UCL, algorithm 2e.\n");
printf("Generated with: uclpack --best --2e rockbox.bin imageN.ucl\n");
exit(0);
}
memset(aFirmware, 0xFF, sizeof(aFirmware));
/******* process template *******/
pFile = fopen(argv[2], "rb"); // open the template
if (pFile == NULL)
{
printf("Template file %s not found!\n", argv[2]);
exit(1);
}
size = fread(aFirmware, 1, 256, pFile); // need only the header
fclose(pFile);
if (size < 256) // need at least the firmware header
{
printf("Template file %s too small, need at least the header!\n", argv[2]);
exit(2);
}
if (strncmp(aFirmware, "ARCH", 4) == 0)
{
hasBootRom = TRUE;
pos = 256; // place bootloader after this "boot block"
}
else if (Read32(aFirmware) == 0x0200)
{
hasBootRom = FALSE;
pos = 0; // directly start with the bootloader
template_F8 = Read32(aFirmware + 0xF8); // my platform ID and future info
template_FC = Read32(aFirmware + 0xFC); // use mask+version from template
}
else
{
printf("Template file %s invalid!\n", argv[2]);
exit(3);
}
/******* process bootloader *******/
pFile = fopen(argv[3], "rb"); // open the bootloader
if (pFile == NULL)
{
printf("Bootloader file %s not found!\n", argv[3]);
exit(4);
}
if (hasBootRom && fseek(pFile, 6, SEEK_SET)) // skip the ajz header
{
printf("Bootloader file %s too short!\n", argv[3]);
exit(5);
}
// place bootloader after header
size = fread(aFirmware + pos, 1, sizeof(aFirmware) - pos, pFile);
fclose(pFile);
if (hasBootRom)
{
Write32(aFirmware + 4, BOOTLOAD_DEST); // boot code destination address
for (i=0x08; i<=0x28; i+=8)
{
Write32(aFirmware + i, BOOTLOAD_SCR); // boot code source address
Write32(aFirmware + i + 4, size); // boot code size
}
}
else
{
Write32(aFirmware + 0xF8, template_F8); // values from template
Write32(aFirmware + 0xFC, template_FC); // mask and version
}
size = (size + 3) & ~3; // make shure it's 32 bit aligned
pos += size; // prepare position for first image
/******* process images *******/
for (i = 4; i < argc; i++)
{
pos = PlaceImage(argv[i], pos, aFirmware, sizeof(aFirmware));
if (i < argc-1)
{ // not the last: round up to next flash sector
pos = (pos + SECTORSIZE-1) & ~(SECTORSIZE-1);
}
}
/******* append CRC32 checksum *******/
crc32 = CalcCRC32(aFirmware, pos);
Write32(aFirmware + pos, crc32);
pos += sizeof(crc32); // 4 bytes
/******* save result to output file *******/
pFile = fopen(argv[1], "wb"); // open the output file
if (pFile == NULL)
{
printf("Output file %s cannot be created!\n", argv[1]);
exit(9);
}
size = fwrite(aFirmware, 1, pos, pFile);
fclose(pFile);
if (size != pos)
{
printf("Error writing %d bytes to output file %s!\n", pos, argv[1]);
exit(10);
}
printf("Firmware file generated with %d bytes.\n", pos);
return 0;
}

View file

@ -0,0 +1,96 @@
# Microsoft Developer Studio Project File - Name="make_firmware" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Console Application" 0x0103
CFG=make_firmware - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE NMAKE /f "make_firmware.mak".
!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "make_firmware.mak" CFG="make_firmware - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "make_firmware - Win32 Release" (based on "Win32 (x86) Console Application")
!MESSAGE "make_firmware - Win32 Debug" (based on "Win32 (x86) Console Application")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
RSC=rc.exe
!IF "$(CFG)" == "make_firmware - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release"
# PROP BASE Intermediate_Dir "Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release"
# PROP Intermediate_Dir "Release"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /c
# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX"stdafx.h" /FD /c
# ADD BASE RSC /l 0x407 /d "NDEBUG"
# ADD RSC /l 0x407 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
!ELSEIF "$(CFG)" == "make_firmware - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug"
# PROP BASE Intermediate_Dir "Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug"
# PROP Intermediate_Dir "Debug"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c
# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /YX"stdafx.h" /FD /GZ /c
# ADD BASE RSC /l 0x407 /d "_DEBUG"
# ADD RSC /l 0x407 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
!ENDIF
# Begin Target
# Name "make_firmware - Win32 Release"
# Name "make_firmware - Win32 Debug"
# Begin Group "Source Files"
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File
SOURCE=.\make_firmware.c
# End Source File
# End Group
# Begin Group "Header Files"
# PROP Default_Filter "h;hpp;hxx;hm;inl"
# End Group
# End Target
# End Project

53
flash/minimon/Makefile Normal file
View file

@ -0,0 +1,53 @@
# __________ __ ___.
# Open \______ \ ____ ____ | | _\_ |__ _______ ___
# Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
# Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
# Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
# \/ \/ \/ \/ \/
# $Id$
#
CC = sh-elf-gcc
LD = sh-elf-ld
AR = sh-elf-ar
AS = sh-elf-as
OC = sh-elf-objcopy
FIRMWARE := ../../firmware
TOOLSDIR=../../tools
TARGET = minimon
LDS := $(TARGET).lds
INCLUDES= -I$(FIRMWARE)/export -I. -I$(OBJDIR)
OBJDIR := .
CFLAGS = -fpic -O -W -Wall -m1 -nostdlib -ffreestanding -Wstrict-prototypes -fomit-frame-pointer -fschedule-insns $(INCLUDES) $(DEFINES)
AFLAGS += -small -relax
ifdef DEBUG
DEFINES := -DDEBUG
CFLAGS += -g
endif
SRC := $(wildcard *.c)
OBJS := $(SRC:%.c=$(OBJDIR)/%.o)
LINKFILE = $(OBJDIR)/$(TARGET).lds
$(OBJDIR)/$(TARGET).bin : $(OBJDIR)/$(TARGET).elf
$(OC) -O binary $(OBJDIR)/$(TARGET).elf $(OBJDIR)/$(TARGET).bin
$(TOOLSDIR)/sh2d $(OBJDIR)/$(TARGET).bin -o 0900000 > $(OBJDIR)/$(TARGET).asm
$(OBJDIR)/$(TARGET).elf : $(OBJS)
$(CC) -Os -nostdlib -o $(OBJDIR)/$(TARGET).elf -L$(OBJDIR) -T$(LINKFILE) -Wl,-Map,$(OBJDIR)/$(TARGET).map
clean:
-rm -f $(OBJS) $(OBJDIR)/$(TARGET).asm \
$(OBJDIR)/$(TARGET).bin \
$(OBJDIR)/$(TARGET).elf \
$(OBJDIR)/$(TARGET).map

6
flash/minimon/README Normal file
View file

@ -0,0 +1,6 @@
(c) 2003 by Jörg Hohensohn
MiniMon is the tiny but powerful-enough piece of code that can be loaded
with the UART boot mod.
It allows to read and write memory, flash program, execute code.
This is suitable to reflash the box, load Rockbox or the gdb stub, etc.

156
flash/minimon/minimon.c Normal file
View file

@ -0,0 +1,156 @@
// minimalistic monitor
// to be loaded with the UART boot feature
// capable of reading and writing bytes, commanded by UART
#include "sh7034.h"
#include "minimon.h"
// scalar types
typedef unsigned char UINT8;
typedef unsigned short UINT16;
typedef unsigned long UINT32;
typedef void(*tpFunc)(void); // type for exec
typedef int(*tpMain)(void); // type for start vector to main()
// prototypes
int main(void);
// our binary has to start with a vector to the entry point
tpMain start_vector[] __attribute__ ((section (".startvector"))) = {main};
UINT8 uart_read(void)
{
UINT8 byte;
while (!(SSR1 & SCI_RDRF)); // wait for char to be available
byte = RDR1;
SSR1 &= ~SCI_RDRF;
return byte;
}
void uart_write(UINT8 byte)
{
while (!(SSR1 & SCI_TDRE)); // wait for transmit buffer empty
TDR1 = byte;
SSR1 &= ~SCI_TDRE;
}
int main(void)
{
UINT8 cmd;
UINT32 addr;
UINT32 size;
UINT32 content;
volatile UINT8* paddr = 0;
volatile UINT8* pflash; // flash base address
while (1)
{
cmd = uart_read();
switch (cmd)
{
case BAUDRATE:
content = uart_read();
uart_write(cmd); // acknowledge by returning the command value
while (!(SSR1 & SCI_TEND)); // wait for empty shift register, before changing baudrate
BRR1 = content;
break;
case ADDRESS:
addr = (uart_read() << 24) | (uart_read() << 16) | (uart_read() << 8) | uart_read();
paddr = (UINT8*)addr;
pflash = (UINT8*)(addr & 0xFFF80000); // round down to 512k align
uart_write(cmd); // acknowledge by returning the command value
break;
case BYTE_READ:
content = *paddr++;
uart_write(content); // the content is the ack
break;
case BYTE_WRITE:
content = uart_read();
*paddr++ = content;
uart_write(cmd); // acknowledge by returning the command value
break;
case BYTE_READ16:
size = 16;
while (size--)
{
content = *paddr++;
uart_write(content); // the content is the ack
}
break;
case BYTE_WRITE16:
size = 16;
while (size--)
{
content = uart_read();
*paddr++ = content;
}
uart_write(cmd); // acknowledge by returning the command value
break;
case BYTE_FLASH:
content = uart_read();
pflash[0x5555] = 0xAA; // set flash to command mode
pflash[0x2AAA] = 0x55;
pflash[0x5555] = 0xA0; // byte program command
*paddr++ = content;
uart_write(cmd); // acknowledge by returning the command value
break;
case BYTE_FLASH16:
size = 16;
while (size--)
{
content = uart_read();
pflash[0x5555] = 0xAA; // set flash to command mode
pflash[0x2AAA] = 0x55;
pflash[0x5555] = 0xA0; // byte program command
*paddr++ = content;
}
uart_write(cmd); // acknowledge by returning the command value
break;
case HALFWORD_READ:
content = *(UINT16*)paddr;
paddr += 2;
uart_write(content >> 8); // highbyte
uart_write(content & 0xFF); // lowbyte
break;
case HALFWORD_WRITE:
content = uart_read() << 8 | uart_read();
*(UINT16*)paddr = content;
paddr += 2;
uart_write(cmd); // acknowledge by returning the command value
break;
case EXECUTE:
{
tpFunc pFunc = (tpFunc)paddr;
pFunc();
uart_write(cmd); // acknowledge by returning the command value
}
break;
default:
{
volatile UINT16* pPortB = (UINT16*)0x05FFFFC2;
*pPortB |= 1 << 6; // bit 6 is red LED on
uart_write(~cmd); // error acknowledge
}
} // case
}
return 0;
}

24
flash/minimon/minimon.h Normal file
View file

@ -0,0 +1,24 @@
#ifndef _MINIMON_H
#define _MINIMON_H
// Commands
// all multibyte values (address, halfwords) are passed as big endian
// (most significant of the bytes first)
// set the address (all read/write commands will auto-increment it)
#define BAUDRATE 0x00 // followed by BRR value; response: command byte
#define ADDRESS 0x01 // followed by 4 bytes address; response: command byte
#define BYTE_READ 0x02 // response: 1 byte content
#define BYTE_WRITE 0x03 // followed by 1 byte content; response: command byte
#define BYTE_READ16 0x04 // response: 16 bytes content
#define BYTE_WRITE16 0x05 // followed by 16 bytes; response: command byte
#define BYTE_FLASH 0x06 // followed by 1 byte content; response: command byte
#define BYTE_FLASH16 0x07 // followed by 16 bytes; response: command byte
#define HALFWORD_READ 0x08 // response: 2 byte content
#define HALFWORD_WRITE 0x09 // followed by 2 byte content; response: command byte
#define EXECUTE 0x0A // response: command byte if call returns
#define VERSION 0x0B // response: version
#endif // _MINIMON_H

60
flash/minimon/minimon.lds Normal file
View file

@ -0,0 +1,60 @@
OUTPUT_FORMAT(elf32-sh)
INPUT(minimon.o)
MEMORY
{
DRAM : ORIGIN = 0x09000000, LENGTH = 0x200000
}
SECTIONS
{
.startvector :
{
*(.startvector)
. = ALIGN(0x4);
} > DRAM
.got :
{
*(.got)
} > DRAM
.got.plt :
{
*(.got.plt)
} > DRAM
.rela.got :
{
*(.rela.got)
} > DRAM
.text :
{
. = ALIGN(0x200);
*(.entry)
*(.text)
. = ALIGN(0x4);
} > DRAM
.data :
{
*(.data)
} > DRAM
.rodata :
{
*(.rodata)
. = ALIGN(0x4);
} > DRAM
.bss :
{
*(.bss)
} > DRAM
.stack :
{
*(.stack)
} > DRAM
}

8
flash/uart_boot/README Normal file
View file

@ -0,0 +1,8 @@
(c) 2003 by Jörg Hohensohn
This is the client side for MiniMon, a command line program that communicates with it.
It can be used to reflash a box from ground up, load a program like gdb stub or Rockbox,
and other diagnostics.
Current implementation is for Windows, but with a different UART implementation
it should work for other platforms (Linux) as well.

738
flash/uart_boot/client.c Normal file
View file

@ -0,0 +1,738 @@
// client.cpp : functions for monitor download and communication.
//
#include <stdio.h>
#include <stdlib.h>
#include "scalar_types.h" // (U)INT8/16/32
#include "Uart.h" // platform abstraction for UART
#include "minimon.h" // protocol of my little monitor
// do the baudrate configuration for the Player
int ConfigFirstlevelPlayer (tUartHandle serial_handle)
{
UINT32 result_nbr;
if(!UartConfig(serial_handle, 4800, eMARKPARITY, eTWOSTOPBITS, 8))
{
UINT32 dwErr = GET_LAST_ERR();
printf("Error %d setting up COM params for baudrate byte\n", dwErr);
exit(1);
}
// this will read as 0x19 when viewed with 2300 baud like the player does
result_nbr = UartWrite(serial_handle, (UINT8*)"\x86\xC0", 2);
if (result_nbr != 2)
{
UINT32 dwErr = GET_LAST_ERR();
printf("Error %d setting up COM params for baudrate byte\n", dwErr);
}
SLEEP(100); // wait for the chars to be sent, is there a better way?
// the read 0x19 means 14423 baud with 12 MHz
if(!UartConfig(serial_handle, 14400, eNOPARITY, eONESTOPBIT, 8))
{
printf("Error setting up COM params for 1st level loader\n");
exit(1);
}
return 0;
}
// do the baudrate configuration for the Recoder/FM
int ConfigFirstlevelRecorder (tUartHandle serial_handle)
{
UINT32 result_nbr;
if(!UartConfig(serial_handle, 4800, eNOPARITY, eTWOSTOPBITS, 8))
{
UINT32 dwErr = GET_LAST_ERR();
printf("Error %d setting up COM params for baudrate byte\n", dwErr);
exit(1);
}
// this will read as 0x08 when viewed with 2120 baud like the recorder does
result_nbr = UartWrite(serial_handle, (UINT8*)"\x00\x00", 2);
if(result_nbr != 2)
{
printf("Error transmitting baudrate byte\n");
exit(1);
}
SLEEP(100); // wait for the chars to be sent, is there a better way?
// the read 0x08 means 38400 baud with 11.0592 MHz
if(!UartConfig(serial_handle, 38400, eNOPARITY, eONESTOPBIT, 8))
{
UINT32 dwErr = GET_LAST_ERR();
printf("Error %d setting up COM params for 1st level loader\n", dwErr);
exit(1);
}
return 0;
}
// transfer a byte for the monitor download, with or without acknowledge
int DownloadByte(tUartHandle serial_handle, unsigned char byte, bool bAck)
{
unsigned char received;
bool bRecorder = true; // false for player
while (1)
{
UartWrite(serial_handle, &byte, 1);
if (bAck)
{
UartRead(serial_handle, &received, 1);
if (received == byte)
{
UartWrite(serial_handle, (UINT8*)"\x01", 1); // ack success
break; // exit the loop
}
else
{
printf("Error transmitting monitor byte 0x%02X, got 0x%0X\n", byte, received);
UartWrite(serial_handle, (UINT8*)"\x00", 1); // ack fail, try again
}
}
else
break; // no loop
}
return 1;
}
// download our little monitor, the box must have been just freshly switched on for this to work
int DownloadMonitor(tUartHandle serial_handle, bool bRecorder, char* szFilename)
{
FILE* pFile;
size_t filesize;
UINT8 byte;
unsigned i;
// hard-coded parameters
bool bAck = true; // configure if acknowledged download (without useful for remote pin boot)
UINT32 TargetLoad = 0x0FFFF000; // target load address
pFile = fopen(szFilename, "rb");
if (pFile == NULL)
{
printf("\nMonitor file %s not found, exiting\n", szFilename);
exit(1);
}
// determine file size
fseek(pFile, 0, SEEK_END);
filesize = ftell(pFile);
fseek(pFile, 0, SEEK_SET);
// This is _really_ tricky! The box expects a BRR value in a nonstandard baudrate,
// which a PC can't generate. I'm using a higher one with some wild settings
// to generate a pulse series that:
// 1) looks like a stable byte when sampled with the nonstandard baudrate
// 2) gives a BRR value to the box which results in a baudrate the PC can also use
if (bRecorder)
{
ConfigFirstlevelRecorder(serial_handle);
}
else
{
ConfigFirstlevelPlayer(serial_handle);
}
UartWrite(serial_handle, bAck ? (UINT8*)"\x01" : (UINT8*)"\x00", 1); // ACK mode
// transmit the size, little endian
DownloadByte(serial_handle, (UINT8)( filesize & 0xFF), bAck);
DownloadByte(serial_handle, (UINT8)((filesize>>8) & 0xFF), bAck);
DownloadByte(serial_handle, (UINT8)((filesize>>16) & 0xFF), bAck);
DownloadByte(serial_handle, (UINT8)((filesize>>24) & 0xFF), bAck);
// transmit the load address, little endian
DownloadByte(serial_handle, (UINT8)( TargetLoad & 0xFF), bAck);
DownloadByte(serial_handle, (UINT8)((TargetLoad>>8) & 0xFF), bAck);
DownloadByte(serial_handle, (UINT8)((TargetLoad>>16) & 0xFF), bAck);
DownloadByte(serial_handle, (UINT8)((TargetLoad>>24) & 0xFF), bAck);
// transmit the command byte
DownloadByte(serial_handle, 0xFF, bAck); // 0xFF means execute the transferred image
// transmit the image
for (i=0; i<filesize; i++)
{
fread(&byte, 1, 1, pFile);
DownloadByte(serial_handle, byte, bAck);
}
fclose (pFile);
// now the image should have been started, red LED off
return 0;
}
// wait for a fixed string to be received (no foolproof algorithm,
// may overlook if the searched string contains repeatitions)
int WaitForString(tUartHandle serial_handle, char* pszWait)
{
int i = 0;
unsigned char received;
while(pszWait[i] != '\0')
{
UartRead(serial_handle, &received, 1);
printf("%c", received); // debug
if (received == pszWait[i])
i++; // continue
else
i=0; // mismatch, start over
}
return 0;
}
// send a sting and check the echo
int SendWithEcho(tUartHandle serial_handle, char* pszSend)
{
int i = 0;
unsigned char received;
while(pszSend[i] != '\0')
{
UartWrite(serial_handle, (unsigned char*)(pszSend + i), 1); // send char
do
{
UartRead(serial_handle, &received, 1); // receive echo
printf("%c", received); // debug
}
while (received != pszSend[i]); // should normally be equal
i++; // next char
}
return 0;
}
// rarely used variant: download our monitor using the built-in Archos monitor
int DownloadArchosMonitor(tUartHandle serial_handle, char* szFilename)
{
FILE* pFile;
size_t filesize;
UINT8 byte;
UINT16 checksum = 0;
unsigned i;
// the onboard monitor uses 115200 baud
if(!UartConfig(serial_handle, 115200, eNOPARITY, eONESTOPBIT, 8))
{
UINT32 dwErr = GET_LAST_ERR();
printf("Error %d setting up COM params for baudrate %d\n", dwErr, 115200);
exit(1);
}
// wait for receiving "#SERIAL#"
WaitForString(serial_handle, "#SERIAL#");
// send magic "SRL" command to get interactive mode
SendWithEcho(serial_handle, "SRL\r");
// wait for menu completion: "ROOT>" at the end
WaitForString(serial_handle, "ROOT>");
// send upload command "UP"
SendWithEcho(serial_handle, "UP\r");
pFile = fopen(szFilename, "rb");
if (pFile == NULL)
{
printf("\nMonitor file %s not found, exiting\n", szFilename);
exit(1);
}
// determine file size
fseek(pFile, 0, SEEK_END);
filesize = ftell(pFile);
fseek(pFile, 0, SEEK_SET);
// calculate checksum
for (i=0; i<filesize; i++)
{
fread(&byte, 1, 1, pFile);
checksum += byte;
}
fseek(pFile, 0, SEEK_SET);
// send header
// size as 32 bit little endian
byte = (UINT8)( filesize & 0xFF);
UartWrite(serial_handle, &byte, 1);
byte = (UINT8)((filesize>>8) & 0xFF);
UartWrite(serial_handle, &byte, 1);
byte = (UINT8)((filesize>>16) & 0xFF);
UartWrite(serial_handle, &byte, 1);
byte = (UINT8)((filesize>>24) & 0xFF);
UartWrite(serial_handle, &byte, 1);
// checksum as 16 bit little endian
byte = (UINT8)( checksum & 0xFF);
UartWrite(serial_handle, &byte, 1);
byte = (UINT8)((checksum>>8) & 0xFF);
UartWrite(serial_handle, &byte, 1);
UartWrite(serial_handle, (unsigned char*)"\x00", 1); // kind (3 means flash)
UartWrite(serial_handle, (unsigned char*)"\x00", 1); // ignored byte
// wait for monitor to accept data
WaitForString(serial_handle, "#OKCTRL#");
// transmit the image
for (i=0; i<filesize; i++)
{
fread(&byte, 1, 1, pFile);
UartWrite(serial_handle, &byte, 1); // payload
}
fclose (pFile);
UartWrite(serial_handle, (unsigned char*)"\x00", 1); // ignored byte
// wait for menu completion: "ROOT>" at the end
WaitForString(serial_handle, "ROOT>");
// send start program command "SPRO"
SendWithEcho(serial_handle, "SPRO\r");
SLEEP(100); // wait a little while for startup
return 0;
}
/********** Target functions using the Monitor Protocol **********/
// read a byte using the target monitor
UINT8 ReadByte(tUartHandle serial_handle, UINT32 addr)
{
UINT8 send;
UINT8 received;
// send the address command
send = ADDRESS;
UartWrite(serial_handle, &send, 1);
// transmit the address, big endian
send = (UINT8)((addr>>24) & 0xFF);
UartWrite(serial_handle, &send, 1);
send = (UINT8)((addr>>16) & 0xFF);
UartWrite(serial_handle, &send, 1);
send = (UINT8)((addr>>8) & 0xFF);
UartWrite(serial_handle, &send, 1);
send = (UINT8)(addr & 0xFF);
UartWrite(serial_handle, &send, 1);
UartRead(serial_handle, &received, 1); // response
if (received != ADDRESS)
{
printf("Protocol error!\n");
return 1;
}
// send the read command
send = BYTE_READ;
UartWrite(serial_handle, &send, 1);
UartRead(serial_handle, &received, 1); // response
return received;
}
// write a byte using the target monitor
int WriteByte(tUartHandle serial_handle, UINT32 addr, UINT8 byte)
{
UINT8 send;
UINT8 received;
// send the address command
send = ADDRESS;
UartWrite(serial_handle, &send, 1);
// transmit the address, big endian
send = (UINT8)((addr>>24) & 0xFF);
UartWrite(serial_handle, &send, 1);
send = (UINT8)((addr>>16) & 0xFF);
UartWrite(serial_handle, &send, 1);
send = (UINT8)((addr>>8) & 0xFF);
UartWrite(serial_handle, &send, 1);
send = (UINT8)(addr & 0xFF);
UartWrite(serial_handle, &send, 1);
UartRead(serial_handle, &received, 1); // response
if (received != ADDRESS)
{
printf("Protocol error, receiced 0x%02X!\n", received);
return 1;
}
// send the write command
send = BYTE_WRITE;
UartWrite(serial_handle, &send, 1);
// transmit the data
UartWrite(serial_handle, &byte, 1);
UartRead(serial_handle, &received, 1); // response
if (received != BYTE_WRITE)
{
printf("Protocol error!\n");
return 1;
}
return 0;
}
// read many bytes using the target monitor
int ReadByteMultiple(tUartHandle serial_handle, UINT32 addr, UINT32 size, UINT8* pBuffer)
{
UINT8 send, received;
// send the address command
send = ADDRESS;
UartWrite(serial_handle, &send, 1);
// transmit the address, big endian
send = (UINT8)((addr>>24) & 0xFF);
UartWrite(serial_handle, &send, 1);
send = (UINT8)((addr>>16) & 0xFF);
UartWrite(serial_handle, &send, 1);
send = (UINT8)((addr>>8) & 0xFF);
UartWrite(serial_handle, &send, 1);
send = (UINT8)(addr & 0xFF);
UartWrite(serial_handle, &send, 1);
UartRead(serial_handle, &received, 1); // response
if (received != ADDRESS)
{
printf("Protocol error!\n");
return 1;
}
while (size)
{
if (size >= 16)
{ // we can use a "burst" command
send = BYTE_READ16;
UartWrite(serial_handle, &send, 1); // send the read command
UartRead(serial_handle, pBuffer, 16); // data response
pBuffer += 16;
size -= 16;
}
else
{ // use single byte command
send = BYTE_READ;
UartWrite(serial_handle, &send, 1); // send the read command
UartRead(serial_handle, pBuffer++, 1); // data response
size--;
}
}
return 0;
}
// write many bytes using the target monitor
int WriteByteMultiple(tUartHandle serial_handle, UINT32 addr, UINT32 size, UINT8* pBuffer)
{
UINT8 send, received;
// send the address command
send = ADDRESS;
UartWrite(serial_handle, &send, 1);
// transmit the address, big endian
send = (UINT8)((addr>>24) & 0xFF);
UartWrite(serial_handle, &send, 1);
send = (UINT8)((addr>>16) & 0xFF);
UartWrite(serial_handle, &send, 1);
send = (UINT8)((addr>>8) & 0xFF);
UartWrite(serial_handle, &send, 1);
send = (UINT8)(addr & 0xFF);
UartWrite(serial_handle, &send, 1);
UartRead(serial_handle, &received, 1); // response
if (received != ADDRESS)
{
printf("Protocol error!\n");
return 1;
}
while (size)
{
if (size >= 16)
{ // we can use a "burst" command
send = BYTE_WRITE16;
UartWrite(serial_handle, &send, 1); // send the write command
UartWrite(serial_handle, pBuffer, 16); // transmit the data
UartRead(serial_handle, &received, 1); // response
if (received != BYTE_WRITE16)
{
printf("Protocol error!\n");
return 1;
}
pBuffer += 16;
size -= 16;
}
else
{ // use single byte command
send = BYTE_WRITE;
UartWrite(serial_handle, &send, 1); // send the write command
UartWrite(serial_handle, pBuffer++, 1); // transmit the data
UartRead(serial_handle, &received, 1); // response
if (received != BYTE_WRITE)
{
printf("Protocol error!\n");
return 1;
}
size--;
}
}
return 0;
}
// write many bytes using the target monitor
int FlashByteMultiple(tUartHandle serial_handle, UINT32 addr, UINT32 size, UINT8* pBuffer)
{
UINT8 send, received;
// send the address command
send = ADDRESS;
UartWrite(serial_handle, &send, 1);
// transmit the address, big endian
send = (UINT8)((addr>>24) & 0xFF);
UartWrite(serial_handle, &send, 1);
send = (UINT8)((addr>>16) & 0xFF);
UartWrite(serial_handle, &send, 1);
send = (UINT8)((addr>>8) & 0xFF);
UartWrite(serial_handle, &send, 1);
send = (UINT8)(addr & 0xFF);
UartWrite(serial_handle, &send, 1);
UartRead(serial_handle, &received, 1); // response
if (received != ADDRESS)
{
printf("Protocol error!\n");
return 1;
}
while (size)
{
if (size >= 16)
{ // we can use a "burst" command
send = BYTE_FLASH16;
UartWrite(serial_handle, &send, 1); // send the write command
UartWrite(serial_handle, pBuffer, 16); // transmit the data
UartRead(serial_handle, &received, 1); // response
if (received != BYTE_FLASH16)
{
printf("Protocol error!\n");
return 1;
}
pBuffer += 16;
size -= 16;
}
else
{ // use single byte command
send = BYTE_FLASH;
UartWrite(serial_handle, &send, 1); // send the write command
UartWrite(serial_handle, pBuffer++, 1); // transmit the data
UartRead(serial_handle, &received, 1); // response
if (received != BYTE_FLASH)
{
printf("Protocol error!\n");
return 1;
}
size--;
}
}
return 0;
}
// read a 16bit halfword using the target monitor
UINT16 ReadHalfword(tUartHandle serial_handle, UINT32 addr)
{
UINT8 send;
UINT8 received;
UINT16 halfword;
// send the address command
send = ADDRESS;
UartWrite(serial_handle, &send, 1);
// transmit the address, big endian
send = (UINT8)((addr>>24) & 0xFF);
UartWrite(serial_handle, &send, 1);
send = (UINT8)((addr>>16) & 0xFF);
UartWrite(serial_handle, &send, 1);
send = (UINT8)((addr>>8) & 0xFF);
UartWrite(serial_handle, &send, 1);
send = (UINT8)(addr & 0xFF);
UartWrite(serial_handle, &send, 1);
UartRead(serial_handle, &received, 1); // response
if (received != ADDRESS)
{
printf("Protocol error!\n");
return 1;
}
// send the read command
send = HALFWORD_READ;
UartWrite(serial_handle, &send, 1);
UartRead(serial_handle, &received, 1); // response
halfword = received << 8; // highbyte
UartRead(serial_handle, &received, 1);
halfword |= received; // lowbyte
return halfword;
}
// write a 16bit halfword using the target monitor
int WriteHalfword(tUartHandle serial_handle, UINT32 addr, UINT16 halfword)
{
UINT8 send;
UINT8 received;
// send the address command
send = ADDRESS;
UartWrite(serial_handle, &send, 1);
// transmit the address, big endian
send = (UINT8)((addr>>24) & 0xFF);
UartWrite(serial_handle, &send, 1);
send = (UINT8)((addr>>16) & 0xFF);
UartWrite(serial_handle, &send, 1);
send = (UINT8)((addr>>8) & 0xFF);
UartWrite(serial_handle, &send, 1);
send = (UINT8)(addr & 0xFF);
UartWrite(serial_handle, &send, 1);
UartRead(serial_handle, &received, 1); // response
if (received != ADDRESS)
{
printf("Protocol error!\n");
return 1;
}
// send the write command
send = HALFWORD_WRITE;
UartWrite(serial_handle, &send, 1);
// transmit the data
send = halfword >> 8; // highbyte
UartWrite(serial_handle, &send, 1);
send = halfword & 0xFF; // lowbyte
UartWrite(serial_handle, &send, 1);
UartRead(serial_handle, &received, 1); // response
if (received != HALFWORD_WRITE)
{
printf("Protocol error!\n");
return 1;
}
return 0;
}
// change baudrate using target monitor
int SetTargetBaudrate(tUartHandle serial_handle, long lClock, long lBaudrate)
{
UINT8 send;
UINT8 received;
UINT8 brr;
long lBRR;
lBRR = lClock / lBaudrate;
lBRR = ((lBRR + 16) / 32) - 1; // with rounding
brr = (UINT8)lBRR;
// send the command
send = BAUDRATE;
UartWrite(serial_handle, &send, 1);
UartWrite(serial_handle, &brr, 1); // send the BRR value
UartRead(serial_handle, &received, 1); // response ack
if (received != BAUDRATE)
{ // bad situation, now we're unclear about the baudrate of the target
printf("Protocol error!\n");
return 1;
}
SLEEP(100); // give it some time to settle
// change our baudrate, too
UartConfig(serial_handle, lBaudrate, eNOPARITY, eONESTOPBIT, 8);
return 0;
}
// call a subroutine using the target monitor
int Execute(tUartHandle serial_handle, UINT32 addr, bool bReturns)
{
UINT8 send;
UINT8 received;
// send the address command
send = ADDRESS;
UartWrite(serial_handle, &send, 1);
// transmit the address, big endian
send = (UINT8)((addr>>24) & 0xFF);
UartWrite(serial_handle, &send, 1);
send = (UINT8)((addr>>16) & 0xFF);
UartWrite(serial_handle, &send, 1);
send = (UINT8)((addr>>8) & 0xFF);
UartWrite(serial_handle, &send, 1);
send = (UINT8)(addr & 0xFF);
UartWrite(serial_handle, &send, 1);
UartRead(serial_handle, &received, 1); // response
if (received != ADDRESS)
{
printf("Protocol error!\n");
return 1;
}
// send the execute command
send = EXECUTE;
UartWrite(serial_handle, &send, 1);
if (bReturns)
{ // we expect the call to return control to minimon
UartRead(serial_handle, &received, 1); // response
if (received != EXECUTE)
{
printf("Protocol error!\n");
return 1;
}
}
return 0;
}

21
flash/uart_boot/client.h Normal file
View file

@ -0,0 +1,21 @@
#ifndef _CLIENT_H
#define _CLIENT_H
// setup function for monitor download
int DownloadMonitor(tUartHandle serial_handle, bool bRecorder, char* szFilename);
int DownloadArchosMonitor(tUartHandle serial_handle, char* szFilename);
// target functions using the Monitor Protocol
UINT8 ReadByte(tUartHandle serial_handle, UINT32 addr);
int WriteByte(tUartHandle serial_handle, UINT32 addr, UINT8 byte);
int ReadByteMultiple(tUartHandle serial_handle, UINT32 addr, UINT32 size, UINT8* pBuffer);
int WriteByteMultiple(tUartHandle serial_handle, UINT32 addr, UINT32 size, UINT8* pBuffer);
int FlashByteMultiple(tUartHandle serial_handle, UINT32 addr, UINT32 size, UINT8* pBuffer);
UINT16 ReadHalfword(tUartHandle serial_handle, UINT32 addr);
int WriteHalfword(tUartHandle serial_handle, UINT32 addr, UINT16 halfword);
int SetTargetBaudrate(tUartHandle serial_handle, long lClock, long lBaudrate);
int Execute(tUartHandle serial_handle, UINT32 addr, bool bReturns);
#endif

77
flash/uart_boot/flash.c Normal file
View file

@ -0,0 +1,77 @@
// flash.cpp : higher-level functions for flashing the chip
//
#include "scalar_types.h" // (U)INT8/16/32
#include "Uart.h" // platform abstraction for UART
#include "client.h" // client functions
// read the manufacturer and device ID
int ReadID(tUartHandle serial_handle, UINT32 base, UINT8* pManufacturerID, UINT8* pDeviceID)
{
base &= 0xFFF80000; // round down to 512k align, to make shure
WriteByte(serial_handle, base + 0x5555, 0xAA); // enter command mode
WriteByte(serial_handle, base + 0x2AAA, 0x55);
WriteByte(serial_handle, base + 0x5555, 0x90); // ID command
SLEEP(20); // Atmel wants 20ms pause here
*pManufacturerID = ReadByte(serial_handle, base + 0);
*pDeviceID = ReadByte(serial_handle, base + 1);
WriteByte(serial_handle, base + 0, 0xF0); // reset flash (back to normal read mode)
SLEEP(20); // Atmel wants 20ms pause here
return 0;
}
// erase the sector which contains the given address
int EraseSector(tUartHandle serial_handle, UINT32 address)
{
UINT32 base = address & 0xFFF80000; // round down to 512k align
WriteByte(serial_handle, base + 0x5555, 0xAA); // enter command mode
WriteByte(serial_handle, base + 0x2AAA, 0x55);
WriteByte(serial_handle, base + 0x5555, 0x80); // eraze command
WriteByte(serial_handle, base + 0x5555, 0xAA); // enter command mode
WriteByte(serial_handle, base + 0x2AAA, 0x55);
WriteByte(serial_handle, address, 0x30); // eraze the sector
SLEEP(25); // sector eraze time: 25ms
return 0;
}
// erase the whole flash
int EraseChip(tUartHandle serial_handle, UINT32 base)
{
base &= 0xFFF80000; // round down to 512k align, to make shure
WriteByte(serial_handle, base + 0x5555, 0xAA); // enter command mode
WriteByte(serial_handle, base + 0x2AAA, 0x55);
WriteByte(serial_handle, base + 0x5555, 0x80); // eraze command
WriteByte(serial_handle, base + 0x5555, 0xAA); // enter command mode
WriteByte(serial_handle, base + 0x2AAA, 0x55);
WriteByte(serial_handle, base + 0x5555, 0x10); // chip eraze command
SLEEP(100); // chip eraze time: 100ms
return 0;
}
// program a bunch of bytes "by hand"
int ProgramBytes(tUartHandle serial_handle, UINT32 address, UINT8* pData, UINT32 size)
{
UINT32 base = address & 0xFFF80000; // round down to 512k align
while (size--)
{
WriteByte(serial_handle, base + 0x5555, 0xAA); // enter command mode
WriteByte(serial_handle, base + 0x2AAA, 0x55);
WriteByte(serial_handle, base + 0x5555, 0xA0); // byte program command
WriteByte(serial_handle, address++, *pData++);
// UART protocol is slow enough such that I don't have to wait 20us here
}
return 0;
}

9
flash/uart_boot/flash.h Normal file
View file

@ -0,0 +1,9 @@
#ifndef _FLASH_H
#define _FLASH_H
int ReadID(tUartHandle serial_handle, UINT32 base, UINT8* pManufacturerID, UINT8* pDeviceID);
int EraseSector(tUartHandle serial_handle, UINT32 address);
int EraseChip(tUartHandle serial_handle, UINT32 base);
int ProgramBytes(tUartHandle serial_handle, UINT32 address, UINT8* pData, UINT32 size);
#endif

23
flash/uart_boot/minimon.h Normal file
View file

@ -0,0 +1,23 @@
#ifndef _MINIMON_H
#define _MINIMON_H
// Commands
// all multibyte values (address, halfwords) are passed as big endian
// (most significant of the bytes first)
// set the address (all read/write commands will auto-increment it)
#define BAUDRATE 0x00 // followed by BRR value; response: command byte
#define ADDRESS 0x01 // followed by 4 bytes address; response: command byte
#define BYTE_READ 0x02 // response: 1 byte content
#define BYTE_WRITE 0x03 // followed by 1 byte content; response: command byte
#define BYTE_READ16 0x04 // response: 16 bytes content
#define BYTE_WRITE16 0x05 // followed by 16 bytes; response: command byte
#define BYTE_FLASH 0x06 // followed by 1 byte content; response: command byte
#define BYTE_FLASH16 0x07 // followed by 16 bytes; response: command byte
#define HALFWORD_READ 0x08 // response: 2 byte content
#define HALFWORD_WRITE 0x09 // followed by 2 byte content; response: command byte
#define EXECUTE 0x0A // response: command byte if call returns
#endif // _MINIMON_H

View file

@ -0,0 +1,44 @@
// this is meant to resolve platform dependency
#ifndef _SCALAR_TYPES_H
#define _SCALAR_TYPES_H
#ifdef WIN32
#include <windows.h>
#define SLEEP Sleep
#define GET_LAST_ERR GetLastError
#endif
// ToDo: add stuff for Linux
#ifndef UINT8
#define UINT8 unsigned char
#endif
#ifndef UINT16
#define UINT16 unsigned short
#endif
#ifndef UINT32
#define UINT32 unsigned long
#endif
#ifndef bool
#define bool int
#endif
#ifndef true
#define true 1
#endif
#ifndef false
#define false 0
#endif
#endif

56
flash/uart_boot/uart.h Normal file
View file

@ -0,0 +1,56 @@
// A general definition for the required UART functionality.
// This will be used to gain platform abstraction.
#ifndef _UART_H
#define _UART_H
// data types
typedef void* tUartHandle;
#define INVALID_UART_HANDLE (tUartHandle)-1
typedef enum
{
eNOPARITY,
eODDPARITY,
eEVENPARITY,
eMARKPARITY,
eSPACEPARITY,
} tParity;
typedef enum
{
eONESTOPBIT,
eONE5STOPBITS,
eTWOSTOPBITS,
} tStopBits;
// prototypes
tUartHandle UartOpen( // returns NULL on error
char* szPortName); // COMx for windows
bool UartConfig( // returns true on success, false on error
tUartHandle handle, // the handle returned from UartOpen()
long lBaudRate, // must be one of the "standard" baudrates
tParity nParity, // what kind of parity
tStopBits nStopBits, // how many stop bits
int nByteSize); // size of the "payload", can be 5 to 8
long UartWrite( // returns how much data was actually transmitted
tUartHandle handle, // the handle returned from UartOpen()
unsigned char* pData, // pointer to the data to be transmitted
long lSize); // how many bytes
long UartRead( // returns how much data was actually received
tUartHandle handle, // the handle returned from UartOpen()
unsigned char* pBuffer, // pointer to the destination
long lSize); // how many bytes to read (pBuffer must have enough room)
void UartClose(tUartHandle handle);
#endif // _UART_H

337
flash/uart_boot/uart_boot.c Normal file
View file

@ -0,0 +1,337 @@
// uart_boot.cpp : Defines the entry point for the console application.
//
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "scalar_types.h" // (U)INT8/16/32
#include "Uart.h" // platform abstraction for UART
#include "client.h" // client functions
#include "flash.h" // flash high level functions
// command line configuration: what shall we do?
struct
{
char* szPort; // COM port to use
bool bRecorder; // it's a recorder
bool bArchos; // use the Archos monitor to load, instead of UART boot
bool bSpindown; // spindown the harddisk
bool bReadID; // read manufacturer+device ID
char* szFlashfile; // file to be programmed
char* szDumpfile; // file to dump into
char* szExecfile; // file with the executable
bool bTest; // debug action
bool bBlink; // blink red LED
bool bNoDownload;
} gCmd;
int ProcessCmdLine(int argc, char* argv[])
{
argc--; // exclude our name
argv++;
memset(&gCmd, 0, sizeof(gCmd));
if (argc == 0)
{
printf("Usage: uart_boot [-option {filename}]\n");
printf(" uses activated UART boot mod, box has to be fresh started\n");
printf("The order of the options does not matter, one letter is sufficient.\n");
printf("Possible options are (in the order of later processing):\n");
printf("-port <name of COM port to use>\n");
printf("-recorder (this is a recorder/FM, default is player if not specified)\n");
printf("-archos (use Archos bootloader, this one needs powerup while program waits)\n");
printf("-nodownload (no MiniMon download, it's already active)\n");
printf("-spindown (spindown the harddisk, else it stays on by default)\n");
printf("-id (read manufacturer and device ID of flash, no checks)\n");
printf("-flash <filename of binary to program into flash>\n");
printf("-dump <filename to write flash content to>\n");
printf("-exec <filename of executable for 0x09000000:0x09000200>\n");
printf("-test (some test action currently under development, don't use!)\n");
printf("-blink (blink red LED forever, meant as diagnostics)\n");
printf("\n");
printf("Examples:\n");
printf("uart_boot -r -p COM1 -s -f flashfile.bin -d dumpfile.bin\n");
printf(" recorder on COM1, spindown HD, program and dump (for e.g. offline verify)\n");
printf("uart_boot -r -p COM2 -e rockbox.bin\n");
printf(" recorder on COM2, load Rockbox from file and start it\n");
exit (0);
}
while (argc)
{
if (!strncmp("-port", *argv, 2))
{
gCmd.szPort = *++argv;
if (--argc <= 0 || **argv == '-')
{
printf("No argument given for option %s, aborting.\n", argv[-1]);
exit (-2);
}
}
else if (!strncmp("-recorder", *argv, 2))
{
gCmd.bRecorder = true;
}
else if (!strncmp("-archos", *argv, 2))
{
gCmd.bArchos = true;
}
else if (!strncmp("-nodownload", *argv, 2))
{
gCmd.bNoDownload = true;
}
else if (!strncmp("-spindown", *argv, 2))
{
gCmd.bSpindown = true;
}
else if (!strncmp("-id", *argv, 2))
{
gCmd.bReadID = true;
}
else if (!strncmp("-flash", *argv, 2))
{
gCmd.szFlashfile = *++argv;
if (--argc <= 0 || **argv == '-')
{
printf("No argument given for option %s, aborting.\n", argv[-1]);
exit (-2);
}
}
else if (!strncmp("-dump", *argv, 2))
{
gCmd.szDumpfile = *++argv;
if (--argc <= 0 || **argv == '-')
{
printf("No argument given for option %s, aborting.\n", argv[-1]);
exit (-3);
}
}
else if (!strncmp("-exec", *argv, 2))
{
gCmd.szExecfile = *++argv;
if (--argc <= 0 || **argv == '-')
{
printf("No argument given for option %s, aborting.\n", argv[-1]);
exit (-4);
}
}
else if (!strncmp("-test", *argv, 2))
{
gCmd.bTest = true;
}
else if (!strncmp("-blink", *argv, 2))
{
gCmd.bBlink = true;
}
else
{
printf("Unknown option %s, aborting. Use 'uart_boot' without options for help.\n", *argv);
exit(-1);
}
argv++;
argc--;
}
return 0;
}
int main(int argc, char* argv[])
{
tUartHandle serial_handle;
UINT16 reg;
FILE* pFile;
size_t size;
UINT8 abFirmware[512*1024]; // blocksize
memset(abFirmware, 0xFF, sizeof(abFirmware));
ProcessCmdLine(argc, argv); // what to do
if (!gCmd.szPort)
{
printf("No serial port given, use 'uart_boot' without parameters for options.\n");
exit(-1);
}
serial_handle = UartOpen(gCmd.szPort); // opening serial port
if (serial_handle == NULL)
{
printf("Cannot open port %s\n", gCmd.szPort);
return -1;
}
if (gCmd.bNoDownload)
{ // just set our speed
if (!UartConfig(serial_handle, gCmd.bRecorder ? 115200 : 14400, eNOPARITY, eONESTOPBIT, 8))
{
printf("Error setting up COM params\n");
exit(1);
}
}
else
{ // download the monitor program
if (gCmd.bArchos)
{
printf("Waiting for box startup to download monitor...");
DownloadArchosMonitor(serial_handle, "minimon_v2.bin"); // load the monitor image
printf("\b\b\b done.\n");
}
else
{
printf("Downloading monitor...");
DownloadMonitor(serial_handle, gCmd.bRecorder, "minimon.bin"); // load the monitor image
// From now on, we can talk to the box.
printf("\b\b\b done.\n");
if (gCmd.bRecorder)
{ // we can be faster
SetTargetBaudrate(serial_handle, 11059200, 115200); // set to 115200
}
}
}
// do the action
if (gCmd.bSpindown)
{
// spindown the disk (works only for master)
UINT32 ata; // address of ATA_ALT_STATUS
printf("Harddisk spindown...");
ata = (gCmd.bRecorder && (ReadHalfword(serial_handle, 0x020000FC) & 0x0100)) ? 0x06200206 : 0x06200306;
WriteHalfword(serial_handle, 0x05FFFFCA, 0xBF99); // PACR2 (was 0xFF99)
WriteHalfword(serial_handle, 0x05FFFFC4, 0x0280); // PAIOR (was 0x0000)
WriteHalfword(serial_handle, 0x05FFFFC0, 0xA27F); // PADR (was 0xA0FF)
while (ReadByte(serial_handle, ata) & 0x80); // ATA_ALT_STATUS & STATUS_BSY
WriteByte(serial_handle, 0x06100107, 0xE0); // ATA_COMMAND = CMD_STANDBY_IMMEDIATE;
//while (ReadByte(serial_handle, ata) & 0x80); // ATA_ALT_STATUS & STATUS_BSY
printf("\b\b\b done.\n");
}
if (gCmd.bReadID)
{
UINT8 bMan, bID;
ReadID(serial_handle, 0x02000000, &bMan, &bID);
printf("Manufacturer ID = 0x%02X, Device ID = 0x%02X\n", bMan, bID);
}
if (gCmd.szFlashfile)
{
// flash a firmware file
printf("Flashing file %s...", gCmd.szFlashfile);
pFile = fopen(gCmd.szFlashfile, "rb");
if (pFile == NULL)
{
printf("\nFlash file %s not found, exiting.\n", gCmd.szFlashfile);
return -2;
}
size = fread(abFirmware, 1, sizeof(abFirmware), pFile);
fclose (pFile);
EraseChip(serial_handle, 0x02000000);
FlashByteMultiple(serial_handle, 0x02000000, size, abFirmware);
printf("\b\b\b done.\n");
}
if (gCmd.szDumpfile)
{
// dump the flash content
printf("Writing flash dump into file %s...", gCmd.szDumpfile);
ReadByteMultiple(serial_handle, 0x02000000, sizeof(abFirmware), abFirmware);
pFile = fopen(gCmd.szDumpfile, "wb");
if (pFile == NULL)
{
printf("\nDump file %s cannot be opened, exiting.\n", gCmd.szDumpfile);
return -3;
}
fwrite(abFirmware, 1, sizeof(abFirmware), pFile);
fclose (pFile);
printf("\b\b\b done.\n");
}
if (gCmd.szExecfile)
{
UINT32 size;
printf("Downloading program...");
// init the DRAM controller like the flash boot does
reg = ReadHalfword(serial_handle, 0x05FFFFCA); // PACR2
reg &= 0xFFFB; // PA1 config: /RAS
reg |= 0x0008;
WriteHalfword(serial_handle, 0x05FFFFCA, reg); // PACR2
reg = 0xAFFF; // CS1, CS3 config: /CASH. /CASL
WriteHalfword(serial_handle, 0x05FFFFEE, reg); // CASCR
reg = ReadHalfword(serial_handle, 0x05FFFFA0); // BCR
reg |= 0x8000; // DRAM enable, default bus
WriteHalfword(serial_handle, 0x05FFFFA0, reg); // BCR
reg = ReadHalfword(serial_handle, 0x05FFFFA2); // WCR1
reg &= 0xFDFD; // 1-cycle CAS
WriteHalfword(serial_handle, 0x05FFFFA2, reg); // WCR1
reg = 0x0E00; // CAS 35%, multiplexed, 10 bit row addr.
WriteHalfword(serial_handle, 0x05FFFFA8, reg); // DCR
reg = 0x5AB0; // refresh, 4 cycle waitstate
WriteHalfword(serial_handle, 0x05FFFFAC, reg); // RCR
reg = 0x9605; // refresh constant
WriteHalfword(serial_handle, 0x05FFFFB2, reg); // RTCOR
reg = 0xA518; // phi/32
WriteHalfword(serial_handle, 0x05FFFFAE, reg); // RTCSR
// download Rockbox/gdb
pFile = fopen(gCmd.szExecfile, "rb");
if (pFile == NULL)
{
printf("\nExecutable file %s cannot be opened, exiting.\n", gCmd.szExecfile);
return -3;
}
size = fread(abFirmware, 1, sizeof(abFirmware), pFile);
WriteByteMultiple(serial_handle, 0x09000000, size, abFirmware);
fclose (pFile);
printf("\b\b\b done.\n");
// start rockbox/gdb
printf("Starting program...");
Execute(serial_handle, 0x09000200, false);
printf("\b\b\b done.\n");
}
if (gCmd.bTest)
{
// test code: query keypad
while (1)
{
WriteByte(serial_handle, 0x05FFFEE8, 0x24); // ADCSR
while (!(ReadByte(serial_handle, 0x05FFFEE8) & 0x80));
reg = ReadHalfword(serial_handle, 0x05FFFEE0); // ADDRA
printf("ADC(4): %d\n", reg>>6);
}
}
if (gCmd.bBlink)
{
// blinking LED
UINT8 byte;
printf("Flashing red LED forever... (stop with Ctrl-C)\n");
byte = ReadByte(serial_handle, 0x05FFFFC3);
while (1)
{
byte ^= 0x40;
WriteByte(serial_handle, 0x05FFFFC3, byte);
Sleep(200);
}
}
return 0;
}

View file

@ -0,0 +1,130 @@
# Microsoft Developer Studio Project File - Name="uart_boot" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Console Application" 0x0103
CFG=uart_boot - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE NMAKE /f "uart_boot.mak".
!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "uart_boot.mak" CFG="uart_boot - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "uart_boot - Win32 Release" (based on "Win32 (x86) Console Application")
!MESSAGE "uart_boot - Win32 Debug" (based on "Win32 (x86) Console Application")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
RSC=rc.exe
!IF "$(CFG)" == "uart_boot - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release"
# PROP BASE Intermediate_Dir "Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release"
# PROP Intermediate_Dir "Release"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /c
# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /FR /FD /c
# SUBTRACT CPP /YX /Yc /Yu
# ADD BASE RSC /l 0x407 /d "NDEBUG"
# ADD RSC /l 0x407 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
!ELSEIF "$(CFG)" == "uart_boot - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug"
# PROP BASE Intermediate_Dir "Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug"
# PROP Intermediate_Dir "Debug"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c
# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /FD /GZ /c
# SUBTRACT CPP /YX /Yc /Yu
# ADD BASE RSC /l 0x407 /d "_DEBUG"
# ADD RSC /l 0x407 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
!ENDIF
# Begin Target
# Name "uart_boot - Win32 Release"
# Name "uart_boot - Win32 Debug"
# Begin Group "Source Files"
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File
SOURCE=.\client.c
# End Source File
# Begin Source File
SOURCE=.\flash.c
# End Source File
# Begin Source File
SOURCE=.\uart_boot.c
# End Source File
# Begin Source File
SOURCE=.\uart_win.c
# End Source File
# End Group
# Begin Group "Header Files"
# PROP Default_Filter "h;hpp;hxx;hm;inl"
# Begin Source File
SOURCE=.\client.h
# End Source File
# Begin Source File
SOURCE=.\flash.h
# End Source File
# Begin Source File
SOURCE=.\minimon.h
# End Source File
# Begin Source File
SOURCE=.\scalar_types.h
# End Source File
# Begin Source File
SOURCE=.\uart.h
# End Source File
# End Group
# End Target
# End Project

138
flash/uart_boot/uart_win.c Normal file
View file

@ -0,0 +1,138 @@
// UART wrapper implementation for the Win32 platform
// make a new version of this file for different systems, e.g. Linux
#include <windows.h>
#include "scalar_types.h" // (U)INT8/16/32
#include "Uart.h"
// COMx for windows, returns NULL on error
tUartHandle UartOpen(char* szPortName)
{
HANDLE serial_handle;
DCB dcb;
COMMTIMEOUTS cto = { 0, 0, 0, 0, 0 };
memset(&dcb,0,sizeof(dcb));
/* -------------------------------------------------------------------- */
// set DCB to configure the serial port
dcb.DCBlength = sizeof(dcb);
dcb.fOutxCtsFlow = 0;
dcb.fOutxDsrFlow = 0;
dcb.fDtrControl = DTR_CONTROL_ENABLE; // enable for power
dcb.fDsrSensitivity = 0;
dcb.fRtsControl = RTS_CONTROL_ENABLE; // enable for power
dcb.fOutX = 0;
dcb.fInX = 0;
/* ----------------- misc parameters ----- */
dcb.fErrorChar = 0;
dcb.fBinary = 1;
dcb.fNull = 0;
dcb.fAbortOnError = 0;
dcb.wReserved = 0;
dcb.XonLim = 2;
dcb.XoffLim = 4;
dcb.XonChar = 0x13;
dcb.XoffChar = 0x19;
dcb.EvtChar = 0;
/* ----------------- defaults ----- */
dcb.BaudRate = 4800;
dcb.Parity = NOPARITY;
dcb.fParity = 0;
dcb.StopBits = ONESTOPBIT;
dcb.ByteSize = 8;
/* -------------------------------------------------------------------- */
// opening serial port
serial_handle = CreateFile(szPortName, GENERIC_READ | GENERIC_WRITE,
0, NULL, OPEN_EXISTING, FILE_FLAG_WRITE_THROUGH, NULL);
if (serial_handle == INVALID_HANDLE_VALUE)
{
//printf("Cannot open port \n");
return NULL;
}
SetCommMask(serial_handle, 0);
SetCommTimeouts(serial_handle, &cto);
if(!SetCommState(serial_handle, &dcb))
{
//printf("Error setting up COM params\n");
CloseHandle(serial_handle);
return NULL;
}
return serial_handle;
}
// returns true on success, false on error
bool UartConfig(tUartHandle handle, long lBaudRate, tParity nParity, tStopBits nStopBits, int nByteSize)
{
DCB dcb;
if (!GetCommState (handle, &dcb))
{
return false;
}
dcb.BaudRate = lBaudRate;
dcb.Parity = nParity;
dcb.StopBits = nStopBits;
dcb.ByteSize = nByteSize;
if(!SetCommState(handle, &dcb))
{
//DWORD dwErr = GetLastError();
//printf("Error %d setting up COM params for baudrate byte\n", dwErr);
return false;
}
return true;
}
// returns how much data was actually transmitted
long UartWrite(tUartHandle handle, unsigned char* pData, long lSize)
{
BOOL success;
DWORD result_nbr;
success = WriteFile(handle, pData, lSize, &result_nbr, NULL);
if(!success)
{
return 0;
}
return result_nbr;
}
// returns how much data was actually received
long UartRead(tUartHandle handle, unsigned char* pBuffer, long lSize)
{
BOOL success;
DWORD read_nbr;
success = ReadFile(handle, pBuffer, lSize, &read_nbr, NULL);
if(!success)
{
return 0;
}
return read_nbr;
}
void UartClose(tUartHandle handle)
{
if (handle != NULL)
{
CloseHandle(handle);
}
return;
}