pureikyubu/Docs/RE/bs2.txt
ogamespec c21147ccff Cumulative changes all around project, regarding Stage 1
Docs: New TODO moved to EMU, old renamed to old_todo
Docs: Old coding style is deprecated (old_style.txt)
Docs: Removed mention about CubeDocumented and fixed old emails
RE: boot.s, proved first asm line (lis instruction parameter)
RE: Added PAL and NTSC Boot and IPL IDA files
RE: Some work on NTSC IPL (identified many lib calls, including OS, GX)
RE: Added EXI Bootrom descrambler by segher
RE: GXInit
RE: Internal GX lib structures (GXPrivate.h)
RE: More details on lomem (OS versions)
RE: OSInit and OS.c
RE: OSAlloc (heap allocator)
RE: Very first code of Metrowerk runtime (__start.c)
Docs: Added copy of http://gcdev.narod.ru
Source\Utils: Command processor (Cmd.c)
Source\Utils: File wrapper
Source\Utils: Gekko disasm cleaned up and ported to plain C
Source\Utils: Double-linked lists
Source\Utils: Ported old Profiler code
Source\Utils: String utils
2015-09-04 19:45:10 +03:00

409 lines
9.7 KiB
Text

-------------------------------------------------------------------------------
-= NINTENDO GAMECUBE Initial Program Loader RE =-
-------------------------------------------------------------------------------
IPL, or bootrom is located inside on-board Macronix chip (near Flipper),
and connected to EXI bus.
IPL have mapped CPU address space at 0xFFFnnnnn, so exception prefix
bit 25 (IP) in MSR is set after CPU reset and system reset vector offset
is 0xFFF00100.
Small program, called 'BS' is loading actual program code (menu, RTC stuff)
at 0x81300000. This part is called 'BS2'. Probably 'BS' stands for 'Boot
System', like OS is 'Operating System'.
IPL cant be readed after boot neither using CPU, not special EXI bus reads.
After loading of BS2, BS disabling IPL access, by clearing 17th bit of
0xCC006800, then it sets MSR[IP] bit to normal mode (pointing lower memory),
and jumps to BS2 code entrypoint.
BS2 was written on C, using official SDK libraries, probably earlier than
1.0. __start.c seems to be same as usual, except that there is no OSInit()
call (old versions should call OSInit() in main, instead of __start).
Here is the short description of start() routine (you can easily find full
version in your SDK ;) :
// 81300000
__start:
__init_registers() // set stack pointer and static bases (r2, r13)
__init_hardware() // paired-singles and cache init
__init_data() // clear bss ?
. // here goes Debug Monitor stuff
.
.
DBInit() // debug monitor init :)
__init_user() // cpp init
main() // that's actually, IPL (BS2) code
jmp exit() // halt CPU
main() reversing :
------------------
// 813006D4 (in BS2.c)
main()
{
BS2Init();
OSInit();
AD16Init();
AD16WriteReg(0x800);
DVDInit();
AD16WriteReg(0x900);
CARDInit();
AD16WriteReg(0xa00);
0x81302104(); // SRAM, real-time clock (check ?)
__VIInit(0);
VIInit();
AD16WriteReg(0xb00);
0x813004e4(); // setup perf. monitor
__SyncTime(); // update CPU timer by RTC value
0x813022c0(); // perform initial DVD actions and fall back into menu
PADSetSpec(5); // set pad type ('spec') to production
PADInit();
AD16WriteReg(0xc00);
BS2Menu(); // here goes intro and main menu... (BIG one!)
OSHalt("BS2 ERROR >>> SHOULD NEVER REACH HERE");
}
// ----------------------------------------------------------------------------
static float ZeroF;
// 8130045C
void BS2Init()
{
// clear lower memory
memset(0x80000000, 0, 256);
memset(0x80003000, 0, 256);
__OSInitBATs();
// set memory size to 24MB
*(u32 *)0x80000028 = 0x01800000;
// set console type to default retail 1
*(u32 *)0x8000002c = 1;
// upgrade retail
*(u32 *)0x8000002c += *(u32 *)0xcc00302c >> 28;
*(u32 *)&ZeroF = -1;
__OSInitFPRs();
}
// 813003A0 (removed after SDK 1.0 release)
void __OSInitBATs()
{
__asm
{
isync
li r4, 0
mtspr DBAT2L, r4
mtspr DBAT2U, r4
mtspr DBAT3L, r4
mtspr DBAT3U, r4
mtspr IBAT1L, r4
mtspr IBAT1U, r4
mtspr IBAT2L, r4
mtspr IBAT2U, r4
mtspr IBAT3L, r4
mtspr IBAT3U, r4
isync
}
}
// 813003D8 (from OS.c)
void __OSInitFPRs()
{
// FP is already initialzied in __start(),
// so just invalidate all FPRs.
__asm
{
lfs f0, ZeroF
fmr f1, f0
fmr f2, f0
fmr f3, f0
. e
. t
. c
fmr f31, f0
}
}
// maybe later
0x81302104()
{
__OSLockSram();
__OSCheckSram();
__OSGetRTC();
OSTickToCalendarTime();
memset();
__OSUnlockSram();
__OSSyncSram();
}
// maybe later
0x813004e4()
{
OSDisableInterrupts();
OSGetTick();
OSGetTick();
OSGetTick();
__div2i();
__div2i();
PPCMtpmc1();
PPCMtmmcr0();
OSGetTick();
OSGetTick();
PPCMtmmcr0();
PPCMfpmc1();
__div2i();
__div2i();
__div2i();
OSRestoreInterrupts();
}
// update time-base registers by RTC (real-time clock) value
// RTC is number of seconds, since 01 January 00:00:00 2000
void __SyncTime()
{
OSTick rtcValue;
OSSram* sram = __OSLockSram();
if( __OSGetRTC(&rtcValue) == TRUE )
{
// counterBias can be negative value
rtcValue += sram->counterBias;
__OSSetTime( (OSTime)rtcValue * OS_TIMER_CLOCK );
}
__OSUnlockSram(0);
}
static int BS2State = 0;
// just wrapper..
0x813022c0()
{
BS2State = BS2Mach();
}
// 81300A70
// located in __FILE__ = "BS2Mach.c"
int BS2Mach()
{
static int state = 0;
BOOL level = OSDisableInterrupts();
switch(state)
{
case 0:
[r13 - 0x7dc8] = 0x800030d4;
state = 1;
case 1:
__OSGetSystemTime();
... some checks
... lot of mulhwu, subfe and other strange instructions :)
... lazy to find corresponding macro in os.h
if(fail) break;
state = 2;
// Install DVD cover callback
case 2:
if([r13 - 0x7da8] == 0)
{
r3 = [r13 - 0x7dc8]
[r3] = 0
[r13 - 0x7dc4] = 0
[r13 - 0x7dac] = 1
DVDLowSetResetCoverCallback(0);
DVDReset();
[r13 - 0x7da8] = 1
(s64)[r13 - 0x7d9c] = __OSGetSystemTime();
break;
}
__OSGetSystemTime();
bla bla bla
another checks :)
if(fail) break;
DVDLowSetResetCoverCallback(0x813007d8);
DVDReset();
state = 3;
// Read Disk information (ID)
case 3:
DVDReadDiskID(0x8145e620 + 64, 0x80000000, 0x813007e4);
state = 4;
break;
.
.
.
.
.
.
.
// Leave immidiately ?
case 16:
break;
default:
OSHalt("BS2 ERROR >> UNKNOWN STATE");
}
OSRestoreInterrupts(level);
return (DVDLowGetCoverStatus() == 1) ? 19 : step;
}
// 81301154
void BS2Menu()
{
BS2InitAlloc();
}
static OSHeapHandler BS2Heap;
// 81307EA8
void BS2InitAlloc()
{
u8 *arenaLo;
u8 *arenaHi;
u8 *arenaNew;
arenaLo = OSGetArenaLo();
arenaLo = (void *)OSRoundUp32B(arenaLo);
arenaHi = OSGetArenaHi();
arenaHi = (void *)OSRoundDown32B(arenaHi);
arenaNew = OSInitAlloc(0x80800000, arenaHi, 2);
OSSetArenaLo(arenaHi);
BS2Heap = OSCreateHeap(arenaLo, arenaHi);
OSSetCurrentHeap(BS2Heap);
OSAddToHeap(BS2Heap, arenaNew, 0x81100000);
BS2CheckAlloc();
}
// 81307F34
void BS2CheckAlloc()
{
OSCheckHeap(BS2Heap);
}
// 81307F58
void *OSAlloc(long size)
{
void *ptr;
if((ptr = OSAlloc(size)) == 0)
{
OSPanic(?);
}
return ptr;
}
here is the MAP of BS2 libraries code :
---------------------------------------
813014C8 DEMOInit (*)
81307F58 OSAlloc (*)
813327BC PPCMtmmcr0 ;; PPC
813327C4 PPCMfpmc1
813327CC PPCMtpmc1
81332814 OSInit ;; OS
81332EF0 OSInitAlarm
81332F3C OSCreateAlarm
81333688 OSAllocFromHeap
81333784 OSSetCurrentHeap
81333794 OSInitAlloc
81333804 OSCreateHeap
81333870 OSAddToHeap
813338D0 OSCheckHeap
813344C0 OSGetStackPointer
8133491C OSReport
8133499C OSPanic
81334AA4 PPCHalt
81334D4C EXIImm ;; OS EXI (not standalone)
81335134 EXISync
813353C8 EXIProbeReset
8133570C EXISelect
81335838 EXIDeselect
81335D6C EXILock
81335E60 EXIUnlock
81335F54 AD16Init
81336090 AD16WriteReg
813361B0 OSDisableInterrupts
813361C4 OSEnableInterrupts
813361D8 OSRestoreInterrupts
81336DD8 __OSGetRTC
813372B0 __OSLockSram
81337658 __OSUnlockSram
813376A0 __OSSyncSram
813376B0 __OSCheckSram
81338504 OSInitThreadQueue
8133939C OSGetTick
813393B8 __OSSetTime
8133943C __OSGetSystemTime
8133963C OSTicksToCalendarTime
8133AC50 DVDLowGetCoverStatus ;; DVD
8133AB18 DVDLowReset
8133ABD4 DVDLowSetResetCoverCallback
8133B5F0 DVDInit
8133CD18 DVDReadDiskID
8133D0EC DVDReset
8133DBE0 __VIInit ;; VI
8133DDC8 VIInit
8133E6C0 VIConfigure
8133F0B4 VIGetTvFormat
81343114 CARDInit ;; CARD
813480D4 GXInit ;; GX
81349148 GXInitFifoBase
81349230 GXSetCPUFifo
81349340 GXSetGPFifo
813494B8 __GXFifoInit
8134B0AC __GXPEInit
8135A178 __div2i ;; LIBC
8135A394 __mod2i
8135B494 vprintf
(*) that function was slighty modified particulary for BS2 ?
note : European PAL IPL v. 1.0 was used.
-------------------------------------------------------------------------------
org -- ogamespec@gmail.com
Thanks to tmbinc and titanik for their great work!
links :
GCDEV headquarters : http://www.gcdev.com, http://www.gcdev.com/forums
brief description of BS2 run-flow you can find in awesome Titanik's 'GAMECUBE
LOW-LEVEL INFO'.