Difference between revisions of "BIOS"

From PSXDEV
Jump to: navigation, search
(Boot)
Line 34: Line 34:
 
* Воспроизводит заставку (логотип SONY на белом фоне)
 
* Воспроизводит заставку (логотип SONY на белом фоне)
 
* Запускает процедуру Main, которая либо загружает диск (если он вставлен), либо запускает SHELL
 
* Запускает процедуру Main, которая либо загружает диск (если он вставлен), либо запускает SHELL
 +
 +
<syntaxhighlight lang="c">
 +
//
 +
// 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 Sub_BFC06EC4;
 +
}
 +
</syntaxhighlight>
  
 
== Kernel (PlayStation OS) ==
 
== Kernel (PlayStation OS) ==

Revision as of 11:50, 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
//
// 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 Sub_BFC06EC4;
}

Kernel (PlayStation OS)

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

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

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

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

Shell

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

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

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