Difference between revisions of "BIOS"

From PSXDEV
Jump to: navigation, search
(Boot)
Line 339: Line 339:
  
 
     Main ( Config, Exec );
 
     Main ( Config, Exec );
 +
}
 +
</syntaxhighlight>
 +
 +
== Big Main ==
 +
 +
<syntaxhighlight lang="c">
 +
//
 +
// Big Main
 +
//
 +
 +
#define MUTE_SPU() \
 +
word.[0x1F801C00 + 0x186] = 0; \
 +
word.[0x1F801C00 + 0x184] = 0; \
 +
word.[0x1F801C00 + 0x182] = 0; \
 +
word.[0x1F801C00 + 0x180] = 0;
 +
 +
void Main (char *Config, char *Exec )      // 0xBFC067E8
 +
{
 +
//
 +
// 1
 +
//
 +
 +
TraceStep (1);
 +
 +
v0 = sub_BFC03968 ();
 +
 +
sub_BFC03978 ( v0 & 0xFFFFFBFE );
 +
 +
MUTE_SPU ();
 +
 +
//
 +
// 2
 +
//
 +
 +
TraceStep (2);
 +
 +
sub_BFC00420 ();
 +
 +
//
 +
// 3
 +
//
 +
 +
TraceStep (3);
 +
 +
sub_BFC042D0 ();
 +
 +
sub_BFC042A0 ();
 +
 +
sub_BFC0DB10 ();
 +
 +
sub_BFC0DB20 ();
 +
 +
sub_BFC0D9A0 ();
 +
 +
//
 +
// 4
 +
//
 +
 +
TraceStep (4);
 +
 +
MUTE_SPU ();
 +
 +
dword.0x1F801074 = 0;
 +
dword.0x1F801070 = 0;
 +
 +
sub_BFC0DB30 ( dword_B9B0 );
 +
 +
//
 +
// 5
 +
//
 +
 +
TraceStep (5);
 +
 +
printf ( "\n"
 +
"PS-X Realtime Kernel Ver.2.5\n"
 +
"Copyright 1993,1994 (C) Sony Computer Entertainment Inc. \n" );
 +
 +
//
 +
// 6
 +
//
 +
 +
TraceStep (6);
 +
 +
MUTE_SPU ();
 +
 +
sub_BFC02B50 ( 0xA000B940, 0xBFC0E14C, 0xC );
 +
 +
printf ( "KERNEL SETUP!\n" );
 +
 +
sub_BFC0DB40 ( 0xA000E000, 0x2000 );
 +
 +
sub_BFC04610 (4);
 +
 +
sub_BFC0DB50 (0)
 +
 +
sub_BFC0DB60 (3);
 +
 +
sub_BFC04678 ( dword_B944 );
 +
 +
sub_BFC0472C ( 1, dword_B940 );
 +
 +
sub_BFC0DB70 (1);
 +
 +
MUTE_SPU ();
 +
 +
v0 = sub_BFC02240 ( 0xA000B980 );
 +
 +
if ( v0 )
 +
sub_BFC06FA4 ( 0x385 );
 +
 +
//
 +
// 7
 +
//
 +
 +
TraceStep (7);
 +
 +
sub_BFC06FF0 ();
 +
 +
//
 +
// 8
 +
//
 +
 +
TraceStep (8);
 +
 +
dword.0x1F801074 = 0;
 +
dword.0x1F801070 = 0;
 +
 +
sub_BFC073A0 ();
 +
 +
v0 = sub_BFC02240 ( 0xA000B980 );
 +
 +
if ( v0 )
 +
sub_BFC06FA4 ( 0x399 );
 +
 +
v0 = sub_BFC070AC ();
 +
 +
if ( v0 == 1 )
 +
sub_BFC07148 ();
 +
 +
printf ( "\n"
 +
"BOOTSTRAP LOADER Type C Ver 2.1  03-JUL-1994\n"
 +
"Copyright 1993,1994 (C) Sony Computer Entertainment Inc.\n" );
 +
 +
v0 = sub_BFC02240 ( 0xA000B980 );
 +
 +
if ( v0 )
 +
sub_BFC06FA4 ( 0x386 );
 +
 +
//
 +
// 9
 +
//
 +
 +
TraceStep (9);
 +
 +
v0 = sub_BFC02240 ( 0xA000B980);
 +
 +
if ( v0 )
 +
sub_BFC06FA4 (0x387);
 +
 +
var_4 = sub_BFC0D890 ( Config, 1 );
 +
 +
if ( var_4 >= 0 )
 +
{
 +
printf ( "setup file    : %s\n", Config );
 +
 +
v0 = sub_BFC02240 ( 0xA000B980 );
 +
 +
if ( v0 )
 +
sub_BFC06FA4 ( 0x38F );
 +
 +
v1 = sub_BFC0D8B0 ( var_4, 0xA000B070, 0x800 );
 +
 +
if ( v1 )
 +
{
 +
0xA000B070[v1] = 0;
 +
 +
sub_BFC0D8A0 ( var_4 );
 +
 +
v0 = sub_BFC02240 ( 0xA000B980 );
 +
if ( v0 )
 +
sub_BFC06FA4 ( 0x390 );
 +
 +
sub_BFC008A0 ( 0xA000B070, 0xA000B940, 0xA000B8B0 );
 +
}
 +
else
 +
{
 +
sub_BFC02B50 ( 0xA000B940, 0xBFC0E14C, 0xC );
 +
 +
strcpy ( 0xA000B8B0, Exec );
 +
}
 +
}
 +
else
 +
{
 +
v0 = sub_BFC02240 ( 0xA000B980 );
 +
if ( v0 )
 +
sub_BFC06FA4 (0x391);
 +
 +
byte.0x180 = 0;
 +
 +
sub_BFC02B50 ( 0xA000B940, 0xBFC0E14C, 0xC );
 +
 +
strcpy ( 0xA000B8B0, Exec );
 +
}
 +
 +
//
 +
//
 +
//
 +
 +
v0 = sub_BFC02240 ( 0xA000B980 );
 +
if ( v0 )
 +
sub_BFC06FA4 ( 0x388 );
 +
 +
sub_BFC06F28 ();
 +
 +
printf ( "boot file    : %s\n", 0xA000B8B0 );
 +
 +
v0 = sub_BFC02240 ( 0xA000B980 );
 +
if ( v0 )
 +
sub_BFC06FA4 ( 0x389 );
 +
 +
sub_BFC0D850 ();
 +
 +
v0 = sub_BFC03A18 (0xA000B8B0, 0xA000B870 );
 +
 +
if ( v0 == 0 )
 +
sub_BFC06FA4 ( 0x38A );
 +
 +
printf ( "EXEC:PC0(%08x)  T_ADDR(%08x)  T_SIZE(%08x)\n", dword_B870, dword_B878, dword_B87C );
 +
 +
printf ( "boot address  : %08x %08x\n"
 +
"Execute !\n\n", dword_B870, dword_B948 );
 +
 +
dword_B890 = dword_B948;
 +
dword_B894 = 0;
 +
 +
printf ( "                S_ADDR(%08x)  S_SIZE(%08)\n", dword_B948, 0 );
 +
 +
sub_BFC0D960 ();
 +
 +
v0 = sub_BFC02240 ( 0xA000B980 );
 +
if ( v0 )
 +
sub_BFC06FA4 ( 0x38B );
 +
 +
sub_BFC0D570 (0xA000B870, 1, 0 );
 +
 +
printf ( "End of Main\n" );
 +
 +
sub_BFC06FA4 (0x38C);
 
}
 
}
 
</syntaxhighlight>
 
</syntaxhighlight>

Revision as of 14:17, 5 June 2015

512 KB ROM содержит стартовый загрузчик BIOS, копию ядра (kernel) PlayStation OS, а также "оболочку" (shell), которая открывается, если в консоль не вставлен игровой диск и содержит менеджер карт памяти и CD-проигрыватель.

Типичный ROM BIOS выглядит примерно вот так :

400px

  • У BIOS PU-7 и старых PU-8 микросхема 40 выводов.
  • Начиная с новых версий PU-8 (и далее) микросхема 32 вывода (в том числе и у PSOne)

Внутри скорее всего ROM с ионной имплантацией по маске.

Contents

Тайминги

Версии BIOS

Вот это сложный вопрос, потому что версии BIOS во-первых отличаются от региона, во вторых они отличаются между моделями материнских плат. И даже внутри одной модели материнки могут быть разные версии BIOS, в зависимости от ревизии материнской платы одной модели.

Эталонной версией BIOS почти все эмуляторы считают SCPH1001.BIN. Этот BIOS был подробно дизассемблирован и считается "стабильным" для работы в эмуляторах.

Boot

Программа начальной загрузки (RESET)

Исполнение начинается с адреса 0xBFC00000

  • Инициализирует недокументированные аппаратные регистры CPU (тайминг и пр.)
  • Очищает память и регистры CPU
  • Если в PSX присутствует устройство PIO - выполняет его программу загрузки
  • Загружает kernel
  • Воспроизводит заставку (логотип SONY на белом фоне)
  • Запускает процедуру Main, которая либо загружает диск (если он вставлен), либо запускает SHELL

Some reversing of SCPH-1001 BIOS :

//
// SCPH1001 Reset
// Written likely on assembler
//
 
Reset ()        // 0xBFC00000
{
 
    dword.0x1F801010 = 0x13243F;
 
    dword.0x1F801060 = 0xB88;       // ram_size?
 
    //
    // 20 nops (pipeline reset?)
    //
 
    nop x 20;
 
    goto Reset2;
}    
 
Reset2 ()       // 0xBFC00150
{
    //
    // More registers
    //
 
    dword.0x1F801020 = 0x31125;
 
    dword.0x1F801000 = 0x1F000000;
 
    dword.0x1F801004 = 0x1F802000;
 
    dword.0x1F801008 = 0x13243F;
 
    dword.0x1F801014 = 0x200931E1;
 
    dword.0x1F801018 = 0x20843;
 
    dword.0x1F80100C = 0x3022;
 
    dword.0x1F80101C = 0x70777;
 
    //
    // Clear CPU registers
    //
 
    gpr[1...31] = 0;
 
    //
    // B/U Control (Lock ICache?)
    //
 
    dword.0xFFFE0130 = 0x804;       // Enable I-Cache + Tag Test Mode
 
    //
    // COP0
    //
 
    COP0.SR = 0x10000;      // Isolate cache from bus
 
    //
    // Clear instruction cache Tag memory (Cache line = 16 bytes)
    //
 
    for ( int Addr=0; Addr<0x1000; Addr += 0x80 )
    {
        dword.[Addr] = 0;
        dword.[Addr + 0x10] = 0;
        dword.[Addr + 0x20] = 0;
        dword.[Addr + 0x30] = 0;
        dword.[Addr + 0x40] = 0;
        dword.[Addr + 0x50] = 0;
        dword.[Addr + 0x60] = 0;
        dword.[Addr + 0x70] = 0;
    }
 
    //
    // COP0
    //
 
    COP0.SR = 0;
 
    //
    // BIU/Cache configuration
    //
 
    dword.0xFFFE0130 = 0x800;       // Enable I-Cache
 
    //
    // COP0
    //
 
    COP0.SR = 0x10000;          // Isolate cache from bus
 
    //
    // Clear instruction cache lines
    //
 
    for ( int Addr=0; Addr<0x1000; Addr += 0x80 )
    {
        dword.[Addr] = 0;
        dword.[Addr + 0x4] = 0;
        dword.[Addr + 0x8] = 0;
        dword.[Addr + 0xC] = 0;
        dword.[Addr + 0x10] = 0;
        dword.[Addr + 0x14] = 0;
        dword.[Addr + 0x18] = 0;
        dword.[Addr + 0x1C] = 0;
        dword.[Addr + 0x20] = 0;
        dword.[Addr + 0x24] = 0;
        dword.[Addr + 0x28] = 0;
        dword.[Addr + 0x2C] = 0;
        dword.[Addr + 0x30] = 0;
        dword.[Addr + 0x34] = 0;
        dword.[Addr + 0x38] = 0;
        dword.[Addr + 0x3C] = 0;
        dword.[Addr + 0x40] = 0;
        dword.[Addr + 0x44] = 0;
        dword.[Addr + 0x48] = 0;
        dword.[Addr + 0x4C] = 0;
        dword.[Addr + 0x50] = 0;
        dword.[Addr + 0x54] = 0;
        dword.[Addr + 0x58] = 0;
        dword.[Addr + 0x5C] = 0;
        dword.[Addr + 0x60] = 0;
        dword.[Addr + 0x64] = 0;
        dword.[Addr + 0x68] = 0;
        dword.[Addr + 0x6C] = 0;
        dword.[Addr + 0x70] = 0;
        dword.[Addr + 0x74] = 0;
        dword.[Addr + 0x78] = 0;
        dword.[Addr + 0x7C] = 0;                                
    }
 
    //
    // COP0
    //
 
    COP0.SR = 0;
 
    //
    // Read memory 8 times
    //
 
    t1 = dword.0xA0000000;
    t1 = dword.0xA0000000;
    t1 = dword.0xA0000000;
    t1 = dword.0xA0000000;
    t1 = dword.0xA0000000;
    t1 = dword.0xA0000000;
    t1 = dword.0xA0000000;
    t1 = dword.0xA0000000;
 
    //
    // BIU/Cache default configuration
    //
 
    dword.0xFFFE0130 = 0x1E988;         // D-Cache as Scratchpad
                                        // Enable D-Cache
                                        // Enable I-Cache 
                                        // Enable Bus Grant
                                        // No wait state
                                        // Enable Read Priority
                                        // Enable Load Scheduling
 
    //
    // Reset COP0 regs
    //
 
    COP0.Reg7 = 0;
    COP0.EntryLo1 = 0;
    COP0.PageMask = 0;
    COP0.Wired = 0;
    COP0.Count = 0;
    COP0.Compare = 0;
    COP0.SR = 0;
    COP0.Cause = 0;
 
    //
    // Clear 0xA0009000
    //
 
    memset ( 0xA0009000, 0, 0x3160 );
 
    //
    // Set initial context
    //
 
    CPU.SP = 0x801FFF00;
    CPU.GP = 0xA0010FF0;
    CPU.FP = CPU.SP;
 
    //
    // ram_size ?
    //
 
    dword.0x1F801060 = 0xB88;
 
    dword.0x60 = 2;
    dword.0x64 = 0;
    dword.0x68 = 0xff;
 
    //
    // Mute SPU
    //
 
    word.[0x1F801C00 + 0x180] = 0;      // Mainvolume Left
    word.[0x1F801C00 + 0x182] = 0;      // Mainvolume Right
    word.[0x1F801C00 + 0x184] = 0;      // Reverb depth left
    word.[0x1F801C00 + 0x186] = 0;      // Reverb depth right
 
    goto Reset3;
}
 
//
// Following boot code written on C for sure (has C prolog/epilog in code)
//
 
Reset3 ()   // 0xBFC06EC4
{
    int Present;
 
    TraceStep (0xF);
 
    word.[0x1F801C00 + 0x186] = 0;
    word.[0x1F801C00 + 0x184] = 0;
    word.[0x1F801C00 + 0x182] = 0;
    word.[0x1F801C00 + 0x180] = 0;
 
    Present = CheckPIO ();
 
    if ( Present )
        ResetPIO ();
 
    TraceStep (0xE);
 
    dword.0xA000B9B0 = 0;
 
    StartKernel ();
}
 
TraceStep (a0)      // 0xBFC01A60
{
    Bogus1 ();
 
    byte.0x1F802041 = a0 & 0xFF;
}
 
Bogus1 ()       // 0xBFC03990
{
    dword.0xA000B068 = 0;
    dword.0xA000B068 = 0;
    dword.0xA000B068 = 0;
    dword.0xA000B068 = 0;
}
 
//
// PIO Support
//
 
char Licensed[] = "Licensed by Sony Computer Entertainment Inc.";       // 0xBFC0E288
 
int CheckPIO (void)         // 0xBFC0703C
{
    char * Source = Licensed;
    char * Dest = 0x1F000084;       // PIO Header
 
    while ( *Source )
    {
        if ( *Source != *Dest ) break;
 
        Source++;
        Dest++;
    }
 
    if ( *Source ) return 0;
    else return 1;
}
 
void ResetPIO (void)        // 0xBFC0711C
{
    //
    // Run init code in PIO Space
    //
 
    dword.0x1F000080 ();
}
 
void StartKernel ()      // 0xBFC06784
{
    char Config[0x50];
    char Exec[0x50];
 
    strcpy ( Config, "cdrom:" );
    strcat ( Config, "SYSTEM.CNF;1" );
 
    strcpy ( Exec, "cdrom:" );
    strcat ( Exec, "PSX.EXE;1" );
 
    Main ( Config, Exec );
}

Big Main

//
// Big Main
//
 
#define MUTE_SPU() \
	word.[0x1F801C00 + 0x186] = 0; 	\
	word.[0x1F801C00 + 0x184] = 0;	\
	word.[0x1F801C00 + 0x182] = 0;	\
	word.[0x1F801C00 + 0x180] = 0;
 
void Main (char *Config, char *Exec )       // 0xBFC067E8
{
	//
	// 1
	//
 
	TraceStep (1);
 
	v0 = sub_BFC03968 ();
 
	sub_BFC03978 ( v0 & 0xFFFFFBFE );
 
	MUTE_SPU ();
 
	//
	// 2
	//
 
	TraceStep (2);
 
	sub_BFC00420 ();
 
	//
	// 3
	//
 
	TraceStep (3);
 
	sub_BFC042D0 ();
 
	sub_BFC042A0 ();
 
	sub_BFC0DB10 ();
 
	sub_BFC0DB20 ();
 
	sub_BFC0D9A0 ();
 
	//
	// 4
	//
 
	TraceStep (4);
 
	MUTE_SPU ();
 
	dword.0x1F801074 = 0;
	dword.0x1F801070 = 0;
 
	sub_BFC0DB30 ( dword_B9B0 );
 
	//
	// 5
	//
 
	TraceStep (5);
 
	printf ( "\n" 
			 "PS-X Realtime Kernel Ver.2.5\n"
			 "Copyright 1993,1994 (C) Sony Computer Entertainment Inc. \n" );
 
	//
	// 6
	//
 
	TraceStep (6);
 
	MUTE_SPU ();
 
	sub_BFC02B50 ( 0xA000B940, 0xBFC0E14C, 0xC );
 
	printf ( "KERNEL SETUP!\n" );
 
	sub_BFC0DB40 ( 0xA000E000, 0x2000 );
 
	sub_BFC04610 (4);
 
	sub_BFC0DB50 (0)
 
	sub_BFC0DB60 (3);
 
	sub_BFC04678 ( dword_B944 );
 
	sub_BFC0472C ( 1, dword_B940 );
 
	sub_BFC0DB70 (1);
 
	MUTE_SPU ();
 
	v0 = sub_BFC02240 ( 0xA000B980 );
 
	if ( v0 )
		sub_BFC06FA4 ( 0x385 );
 
	//
	// 7
	//
 
	TraceStep (7);
 
	sub_BFC06FF0 ();
 
	//
	// 8
	//
 
	TraceStep (8);
 
	dword.0x1F801074 = 0;
	dword.0x1F801070 = 0;
 
	sub_BFC073A0 ();
 
	v0 = sub_BFC02240 ( 0xA000B980 );
 
	if ( v0 )
		sub_BFC06FA4 ( 0x399 );
 
	v0 = sub_BFC070AC ();
 
	if ( v0 == 1 )
		sub_BFC07148 ();
 
	printf ( "\n" 
			 "BOOTSTRAP LOADER Type C Ver 2.1   03-JUL-1994\n"
			 "Copyright 1993,1994 (C) Sony Computer Entertainment Inc.\n" );
 
	v0 = sub_BFC02240 ( 0xA000B980 );
 
	if ( v0 )
		sub_BFC06FA4 ( 0x386 );
 
	//
	// 9
	//
 
	TraceStep (9);
 
	v0 = sub_BFC02240 ( 0xA000B980);
 
	if ( v0 )
		sub_BFC06FA4 (0x387);
 
	var_4 = sub_BFC0D890 ( Config, 1 );
 
	if ( var_4 >= 0 )
	{
		printf ( "setup file    : %s\n", Config );
 
		v0 = sub_BFC02240 ( 0xA000B980 );
 
		if ( v0 )
			sub_BFC06FA4 ( 0x38F );
 
		v1 = sub_BFC0D8B0 ( var_4, 0xA000B070, 0x800 );
 
		if ( v1 )
		{
			0xA000B070[v1] = 0;
 
			sub_BFC0D8A0 ( var_4 );
 
			v0 = sub_BFC02240 ( 0xA000B980 );
			if ( v0 )
				sub_BFC06FA4 ( 0x390 );
 
			sub_BFC008A0 ( 0xA000B070, 0xA000B940, 0xA000B8B0 );
		}
		else
		{
			sub_BFC02B50 ( 0xA000B940, 0xBFC0E14C, 0xC );
 
			strcpy ( 0xA000B8B0, Exec );
		}
	}
	else
	{
		v0 = sub_BFC02240 ( 0xA000B980 );
		if ( v0 )
			sub_BFC06FA4 (0x391);
 
		byte.0x180 = 0;
 
		sub_BFC02B50 ( 0xA000B940, 0xBFC0E14C, 0xC );
 
		strcpy ( 0xA000B8B0, Exec );
	}
 
	//
	//
	//
 
	v0 = sub_BFC02240 ( 0xA000B980 );
	if ( v0 )
		sub_BFC06FA4 ( 0x388 );
 
	sub_BFC06F28 ();
 
	printf ( "boot file     : %s\n", 0xA000B8B0 );
 
	v0 = sub_BFC02240 ( 0xA000B980 );
	if ( v0 )
		sub_BFC06FA4 ( 0x389 );
 
	sub_BFC0D850 ();
 
	v0 = sub_BFC03A18 (0xA000B8B0, 0xA000B870 );
 
	if ( v0 == 0 )
		sub_BFC06FA4 ( 0x38A );
 
	printf ( "EXEC:PC0(%08x)  T_ADDR(%08x)  T_SIZE(%08x)\n", dword_B870, dword_B878, dword_B87C );
 
	printf ( "boot address  : %08x %08x\n"
			 "Execute !\n\n", dword_B870, dword_B948 );
 
	dword_B890 = dword_B948;
	dword_B894 = 0;
 
	printf ( "                S_ADDR(%08x)  S_SIZE(%08)\n", dword_B948, 0 );
 
	sub_BFC0D960 ();
 
	v0 = sub_BFC02240 ( 0xA000B980 );
	if ( v0 )
		sub_BFC06FA4 ( 0x38B );
 
	sub_BFC0D570 (0xA000B870, 1, 0 );
 
	printf ( "End of Main\n" );
 
	sub_BFC06FA4 (0x38C);
}

Kernel (PlayStation OS)

Ядро PS OS резидентно находится в памяти. Доступ к процедурам ядра производится через специальные таблицы (которые находятся по адресам 0xA0, 0xB0, 0xC0).

Второй способ вызова некоторых механизмов ядра - это инструкция Syscall (но набор её функций ограничен, по сути используется только для EnterCriticalSection / ExitCriticalSection)

Также приложениям доступна специальная "Таблица Таблиц" ядра (ToT), через которую программа может получить различные системные описатели и пр.

Выполнение пользовательских программ происходит в режиме CPU Kernel Mode, поскольку одновременно может быть запущен только один "процесс" (исполняемый файл игры).

Shell

Оболочка BIOS - это специальным образом запакованный исполняемый файл формата PS-X EXE, который находится внутри ROM.

Программа начальной загрузки распаковывает его и загружает на лету в RAM перед запуском.

Оболочка запускается если в привод не вставлен игровой диск.