The example embodiment is a device to play games. It consists of a strong PowerPC-based CPU with some proprietary extensions, a proprietary GPU/Peripheral core (called "Flipper"), including a powerful 3D processor, 24MB of 1T-SRAM, a mini-DVD disc drive, several external interfaces.
The example is meant to be only used with original games, and thus has a protection that boot is only possible from copy protected discs. However, a game called "Phantasy Star Online" contained a possibility to exploit the games' connect to the internet, thus allowing code to be injected and executed (www.gdev.com) - the homebrew scene had started!
The problem is that the boot process with PSO takes very long each time you want to try something, about 1-2 minutes - really not perfect for a nice development cycle. To overcome this, I developed a bios (or bootrom, as or9 would say) replacement, which i want to present here.
As I explained in this dextrose forum post i managed it to program a CPLD to replace the contents of the IPL, or BIOS, or bootrom. The hardware part consists of:
.long 0x52000000 # although being code, it's nearly a no-op.
# this is the sector address sent to memory card
lis r27, 0xcc00 # load base of hardware registers.
# as the bat are already initialized by BS, we
# add 0xC0000000 to the base 0x0C000000.
li r28, 0x0880 # chip select on for memcard slot, low speed
mflr r29 # lr still contains the address of this code - i.e. 0x81300000
li r30, 128 # transfer 128 bytes
li r31, 7 # EXI DMA write
bl do_dma # do dma, and wait for end
lis r29, 0x8100 # now read to 0x81000000, again 128 bytes
li r31, 3 # EXI DMA read
mtlr r29 # set address to be jumped to
do_dma:
stmw r28, 0x6814(r27) # initiate DMA
write_wait:
lmz r5, 0x6820(r27) # read status byte
rlwinm. 0, 5, 31, 31 # extract "in transfer" bit
bne write_wait # wait until cleared
blr # branch back / to code
This code may look a bit confusing at first, but it had to be as small as this, otherwise it wouldn't have fit into the CPLD.
The code sends itself out to the EXI. thus the bytes sent are "52 00 00 00 3f .. .. ..", 128 bytes in total. The memory card expects one command byte, which is 0x52 in this case. after that, it expects the address, 00 00 00 3f in this case, which is the first sector, offset 0x3F. then it expects 4 dummy bytes, and starts sending out the data bytes after that. after it reaches the end of the sector (128 bytes + 6 special bytes for ECC, but we can use them as well), it starts repeating the sector. So after writing out 128 bytes we can read 128 bytes of payload into memory. A special program will shuffle the data around so that after 128 bytes of data the first data of our beloved payload comes out, and gets read into memory. After we finished the exi read dma, we jump there.
This was the first stage bootloader. Now the first sector of the memory card contains 128+6 bytes of a second stage bootloader, which reads the remaining sectors of the card into mem and jumps there. We couldn't do this from the beginning because of the lack of space in the CPLD. the 2nd stage bootloader i wrote fits exactly into 128bytes, but probably can be optimized a bit further. i don't care, since it fits.Now we can load up to (nearly) 512k of user code into memory, thus writing our own IPL replacement. I have started to do that, but it still misses important functions, but can be used to upload DOLs (using network) and execute them (allowing to boot homebrew in a matter of seconds), and start games (using a small apploader).
Pin 3 D1 - SERIAL IN (to card) 4 D2 - CHIP SELECT (to card) 5 D3 - CLK (to card) 10 ACK - SERIAL OUT (from card) 25 GND - GROUND 3.3v - Card VCCFor the pinout of the memory card, take a look at http://members.shaw.ca/cheezWhizzer/GCNCard.htm.
You have to call ./mc with a binary file as argument. It must be a file linked to 0x81000080, with entry point at start. My makefile will produce a file called "main_boot.bin", which is suitable for this. Take care that the number of used pages does not exceed the number of pages read into memory by the second stage bootloader. You can increse them as you like.