mirror of
https://github.com/Polprzewodnikowy/SummerCart64.git
synced 2024-11-28 00:14:14 +01:00
improved boot and CIC detection process
This commit is contained in:
parent
8ecbd6e401
commit
e91adcdb59
@ -7,11 +7,11 @@
|
||||
| id | name | arg0 | arg1 | rsp0 | rsp1 | description |
|
||||
| --- | --------------------- | -------------- | ------------ | ---------------- | -------------- | ---------------------------------------------------------- |
|
||||
| `v` | **IDENTIFIER_GET** | --- | --- | identifier | --- | Get flashcart identifier `SCv2` |
|
||||
| `V` | **VERSION_GET** | --- | --- | version | --- | Get flashcart firmware version |
|
||||
| `V` | **VERSION_GET** | --- | --- | major/minor | revision | Get flashcart firmware version |
|
||||
| `c` | **CONFIG_GET** | config_id | --- | --- | current_value | Get config option |
|
||||
| `C` | **CONFIG_SET** | config_id | new_value | --- | previous_value | Set config option and get previous value |
|
||||
| `c` | **SETTING_GET** | setting_id | --- | --- | current_value | Get persistent setting option |
|
||||
| `C` | **SETTING_SET** | setting_id | new_value | --- | --- | Set persistent setting option |
|
||||
| `a` | **SETTING_GET** | setting_id | --- | --- | current_value | Get persistent setting option |
|
||||
| `A` | **SETTING_SET** | setting_id | new_value | --- | --- | Set persistent setting option |
|
||||
| `t` | **TIME_GET** | --- | --- | time_0 | time_1 | Get current RTC value |
|
||||
| `T` | **TIME_SET** | time_0 | time_1 | --- | --- | Set new RTC value |
|
||||
| `m` | **USB_READ** | pi_address | length | --- | --- | Receive data from USB to flashcart |
|
||||
@ -23,7 +23,7 @@
|
||||
| `s` | **SD_READ** | pi_address | sector_count | --- | --- | Read sectors from SD card to flashcart |
|
||||
| `S` | **SD_WRITE** | pi_address | sector_count | --- | --- | Write sectors from flashcart to SD card |
|
||||
| `D` | **DISK_MAPPING_SET** | pi_address | table_size | --- | --- | Set 64DD disk mapping for SD mode |
|
||||
| `w` | **WRITEBACK_PENDING** | pending_status | --- | --- | --- | Get save writeback status (is write queued to the SD card) |
|
||||
| `w` | **WRITEBACK_PENDING** | --- | --- | pending_status | --- | Get save writeback status (is write queued to the SD card) |
|
||||
| `W` | **WRITEBACK_SD_INFO** | pi_address | --- | --- | --- | Load writeback SD sector table and enable it |
|
||||
| `K` | **FLASH_PROGRAM** | pi_address | length | --- | --- | Program flash with bytes loaded into data buffer |
|
||||
| `p` | **FLASH_WAIT_BUSY** | wait | --- | erase_block_size | --- | Wait until flash ready / get block erase size |
|
||||
|
@ -19,7 +19,7 @@ BUILD_DIR = build
|
||||
SRC_FILES = \
|
||||
startup.S \
|
||||
boot.c \
|
||||
crc32.c \
|
||||
cic.c \
|
||||
display.c \
|
||||
error.c \
|
||||
exception.c \
|
||||
|
@ -13,6 +13,7 @@ SECTIONS {
|
||||
.boot : {
|
||||
KEEP(*(.text.rom_header));
|
||||
KEEP(*(.text.ipl3));
|
||||
. = ALIGN(4k);
|
||||
} > rom
|
||||
|
||||
.framebuffer (NOLOAD) : SUBALIGN(64) {
|
||||
|
@ -1,5 +1,5 @@
|
||||
#include "boot.h"
|
||||
#include "crc32.h"
|
||||
#include "cic.h"
|
||||
#include "io.h"
|
||||
#include "vr4300.h"
|
||||
|
||||
@ -8,28 +8,6 @@ extern uint32_t reboot_start __attribute__((section(".text")));
|
||||
extern size_t reboot_size __attribute__((section(".text")));
|
||||
|
||||
|
||||
typedef struct {
|
||||
const uint32_t crc32;
|
||||
const uint8_t seed;
|
||||
} ipl3_crc32_t;
|
||||
|
||||
static const ipl3_crc32_t ipl3_crc32[] = {
|
||||
{ .crc32 = 0x587BD543, .seed = 0xAC }, // 5101
|
||||
{ .crc32 = 0x6170A4A1, .seed = 0x3F }, // 6101
|
||||
{ .crc32 = 0x009E9EA3, .seed = 0x3F }, // 7102
|
||||
{ .crc32 = 0x90BB6CB5, .seed = 0x3F }, // 6102/7101
|
||||
{ .crc32 = 0x0B050EE0, .seed = 0x78 }, // x103
|
||||
{ .crc32 = 0x98BC2C86, .seed = 0x91 }, // x105
|
||||
{ .crc32 = 0xACC8580A, .seed = 0x85 }, // x106
|
||||
{ .crc32 = 0x0E018159, .seed = 0xDD }, // 5167
|
||||
{ .crc32 = 0x10C68B18, .seed = 0xDD }, // NDXJ0
|
||||
{ .crc32 = 0xBC605D0A, .seed = 0xDD }, // NDDJ0
|
||||
{ .crc32 = 0x502C4466, .seed = 0xDD }, // NDDJ1
|
||||
{ .crc32 = 0x0C965795, .seed = 0xDD }, // NDDJ2
|
||||
{ .crc32 = 0x8FEBA21E, .seed = 0xDE }, // NDDE0
|
||||
};
|
||||
|
||||
|
||||
static io32_t *boot_get_device_base (boot_params_t *params) {
|
||||
io32_t *device_base_address = ROM_CART;
|
||||
if (params->device_type == BOOT_DEVICE_TYPE_64DD) {
|
||||
@ -38,38 +16,26 @@ static io32_t *boot_get_device_base (boot_params_t *params) {
|
||||
return device_base_address;
|
||||
}
|
||||
|
||||
static bool boot_detect_cic_seed (boot_params_t *params) {
|
||||
static void boot_detect_cic_seed (boot_params_t *params) {
|
||||
io32_t *base = boot_get_device_base(params);
|
||||
|
||||
uint32_t ipl3[1008] __attribute__((aligned(8)));
|
||||
uint8_t ipl3[IPL3_LENGTH] __attribute__((aligned(8)));
|
||||
|
||||
pi_dma_read(&base[16], ipl3, sizeof(ipl3));
|
||||
|
||||
uint32_t crc32 = crc32_calculate(ipl3, sizeof(ipl3));
|
||||
|
||||
for (int i = 0; i < sizeof(ipl3_crc32) / sizeof(ipl3_crc32_t); i++) {
|
||||
if (ipl3_crc32[i].crc32 == crc32) {
|
||||
params->cic_seed = ipl3_crc32[i].seed;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
params->cic_seed = cic_get_seed(cic_detect(ipl3));
|
||||
}
|
||||
|
||||
|
||||
void boot (boot_params_t *params) {
|
||||
if (params->tv_type == BOOT_TV_TYPE_PASSTHROUGH) {
|
||||
params->tv_type = OS_INFO->tv_type;
|
||||
}
|
||||
|
||||
if (params->detect_cic_seed) {
|
||||
if (!boot_detect_cic_seed(params)) {
|
||||
params->cic_seed = 0x3F;
|
||||
}
|
||||
boot_detect_cic_seed(params);
|
||||
}
|
||||
|
||||
OS_INFO->mem_size_6105 = OS_INFO->mem_size;
|
||||
|
||||
asm volatile (
|
||||
"li $t1, %[status] \n"
|
||||
"mtc0 $t1, $12 \n" ::
|
||||
|
150
sw/bootloader/src/cic.c
Normal file
150
sw/bootloader/src/cic.c
Normal file
@ -0,0 +1,150 @@
|
||||
#include "cic.h"
|
||||
|
||||
|
||||
static inline uint32_t _get (uint8_t *p, int index) {
|
||||
int i = index * 4;
|
||||
return (p[i] << 24 | p[i + 1] << 16 | p[i + 2] << 8 | p[i + 3]);
|
||||
}
|
||||
|
||||
static inline uint32_t _add (uint32_t a1, uint32_t a2) {
|
||||
return a1 + a2;
|
||||
}
|
||||
|
||||
static inline uint32_t _sub (uint32_t a1, uint32_t a2) {
|
||||
return a1 - a2;
|
||||
}
|
||||
|
||||
static inline uint32_t _mul (uint32_t a1, uint32_t a2) {
|
||||
return a1 * a2;
|
||||
}
|
||||
|
||||
static inline uint32_t _rol (uint32_t a, uint32_t s) {
|
||||
return ((a) << (s)) | ((a) >> (-(s) & 31));
|
||||
}
|
||||
|
||||
static inline uint32_t _ror (uint32_t a, uint32_t s) {
|
||||
return ((a) >> (s)) | ((a) << (-(s) & 31));
|
||||
}
|
||||
|
||||
static uint32_t _sum (uint32_t a0, uint32_t a1, uint32_t a2) {
|
||||
uint64_t prod = ((uint64_t) (a0)) * (a1 == 0 ? a2 : a1);
|
||||
uint32_t hi = (prod >> 32) & 0xFFFFFFFF;
|
||||
uint32_t lo = prod & 0xFFFFFFFF;
|
||||
uint32_t diff = hi - lo;
|
||||
return (diff == 0) ? a0 : diff;
|
||||
};
|
||||
|
||||
static uint64_t cic_calculate_ipl3_checksum (uint8_t *ipl3, uint8_t seed) {
|
||||
const uint32_t MAGIC = 0x6C078965;
|
||||
|
||||
uint32_t data, prev, next;
|
||||
data = prev = next = _get(ipl3, 0);
|
||||
|
||||
uint32_t init = _add(_mul(MAGIC, seed), 1) ^ data;
|
||||
|
||||
uint32_t buf[16];
|
||||
for (int i = 0; i < 16; i++) {
|
||||
buf[i] = init;
|
||||
}
|
||||
|
||||
for (int i = 1; i <= 1008; i++) {
|
||||
prev = data;
|
||||
data = next;
|
||||
|
||||
buf[0] = _add(buf[0], _sum(_sub(1007, i), data, i));
|
||||
buf[1] = _sum(buf[1], data, i);
|
||||
buf[2] = buf[2] ^ data;
|
||||
buf[3] = _add(buf[3], _sum(_add(data, 5), MAGIC, i));
|
||||
buf[4] = _add(buf[4], _ror(data, prev & 0x1F));
|
||||
buf[5] = _add(buf[5], _rol(data, prev >> 27));
|
||||
buf[6] = (data < buf[6]) ? (_add(buf[3], buf[6]) ^ _add(data, i)) : (_add(buf[4], data) ^ buf[6]);
|
||||
buf[7] = _sum(buf[7], _rol(data, prev & 0x1F), i);
|
||||
buf[8] = _sum(buf[8], _ror(data, prev >> 27), i);
|
||||
buf[9] = (prev < data) ? _sum(buf[9], data, i) : _add(buf[9], data);
|
||||
|
||||
if (i == 1008) {
|
||||
break;
|
||||
}
|
||||
|
||||
next = _get(ipl3, i);
|
||||
|
||||
buf[10] = _sum(_add(buf[10], data), next, i);
|
||||
buf[11] = _sum(buf[11] ^ data, next, i);
|
||||
buf[12] = _add(buf[12], buf[8] ^ data);
|
||||
buf[13] = _add(buf[13], _add(_ror(data, data & 0x1F), _ror(next, next & 0x1F)));
|
||||
buf[14] = _sum(_sum(buf[14], _ror(data, prev & 0x1F), i), _ror(next, data & 0x1F), i);
|
||||
buf[15] = _sum(_sum(buf[15], _rol(data, prev >> 27), i), _rol(next, data >> 27), i);
|
||||
}
|
||||
|
||||
uint32_t final_buf[4];
|
||||
for (int i = 0; i < 4; i++) {
|
||||
final_buf[i] = buf[0];
|
||||
}
|
||||
|
||||
for (int i = 0; i < 16; i++) {
|
||||
uint32_t data = buf[i];
|
||||
final_buf[0] = _add(final_buf[0], _ror(data, data & 0x1F));
|
||||
final_buf[1] = (data < final_buf[0]) ? _add(final_buf[1], data) : _sum(final_buf[1], data, i);
|
||||
final_buf[2] = (((data & 0x02) >> 1) == (data & 0x01)) ? _add(final_buf[2], data) : _sum(final_buf[2], data, i);
|
||||
final_buf[3] = ((data & 0x01) == 0x01) ? (final_buf[3] ^ data) : _sum(final_buf[3], data, i);
|
||||
}
|
||||
|
||||
uint32_t final_sum = _sum(final_buf[0], final_buf[1], 16);
|
||||
uint32_t final_xor = final_buf[3] ^ final_buf[2];
|
||||
|
||||
uint64_t checksum = (((((uint64_t) (final_sum)) & 0xFFFF)) << 32) | (final_xor);
|
||||
|
||||
return checksum;
|
||||
}
|
||||
|
||||
|
||||
cic_type_t cic_detect (uint8_t *ipl3) {
|
||||
switch (cic_calculate_ipl3_checksum(ipl3, 0x3F)) {
|
||||
case 0x45CC73EE317AULL: return CIC_6101; // 6101
|
||||
case 0x44160EC5D9AFULL: return CIC_7102; // 7102
|
||||
case 0xA536C0F1D859ULL: return CIC_6102_7101; // 6102 / 7101
|
||||
}
|
||||
switch (cic_calculate_ipl3_checksum(ipl3, 0x78)) {
|
||||
case 0x586FD4709867ULL: return CIC_x103; // 6103 / 7103
|
||||
}
|
||||
switch (cic_calculate_ipl3_checksum(ipl3, 0x85)) {
|
||||
case 0x2BBAD4E6EB74ULL: return CIC_x106; // 6106 / 7106
|
||||
}
|
||||
switch (cic_calculate_ipl3_checksum(ipl3, 0x91)) {
|
||||
case 0x8618A45BC2D3ULL: return CIC_x105; // 6105 / 7105
|
||||
}
|
||||
switch (cic_calculate_ipl3_checksum(ipl3, 0xAC)) {
|
||||
case 0x5930D81014DAULL: return CIC_5101; // Aleck 64
|
||||
}
|
||||
switch (cic_calculate_ipl3_checksum(ipl3, 0xDD)) {
|
||||
case 0x6EE8D9E84970ULL: return CIC_8401; // NDXJ0
|
||||
case 0x6C216495C8B9ULL: return CIC_8301; // NDDJ0
|
||||
case 0xE27F43BA93ACULL: return CIC_8302; // NDDJ1
|
||||
case 0x32B294E2AB90ULL: return CIC_8303; // NDDJ2
|
||||
case 0x083C6C77E0B1ULL: return CIC_5167; // 64DD Cartridge conversion
|
||||
}
|
||||
switch (cic_calculate_ipl3_checksum(ipl3, 0xDE)) {
|
||||
case 0x05BA2EF0A5F1ULL: return CIC_8501; // NDDE0
|
||||
}
|
||||
|
||||
return CIC_UNKNOWN;
|
||||
}
|
||||
|
||||
uint8_t cic_get_seed (cic_type_t cic_type) {
|
||||
switch (cic_type) {
|
||||
case CIC_5101: return 0xAC;
|
||||
case CIC_5167: return 0xDD;
|
||||
case CIC_6101: return 0x3F;
|
||||
case CIC_7102: return 0x3F;
|
||||
case CIC_6102_7101: return 0x3F;
|
||||
case CIC_x103: return 0x78;
|
||||
case CIC_x105: return 0x91;
|
||||
case CIC_x106: return 0x85;
|
||||
case CIC_8301: return 0xDD;
|
||||
case CIC_8302: return 0xDD;
|
||||
case CIC_8303: return 0xDD;
|
||||
case CIC_8401: return 0xDD;
|
||||
case CIC_8501: return 0xDE;
|
||||
default: return 0x3F;
|
||||
}
|
||||
}
|
33
sw/bootloader/src/cic.h
Normal file
33
sw/bootloader/src/cic.h
Normal file
@ -0,0 +1,33 @@
|
||||
#ifndef CIC_H__
|
||||
#define CIC_H__
|
||||
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
#define IPL3_LENGTH (4032)
|
||||
|
||||
|
||||
typedef enum {
|
||||
CIC_5101,
|
||||
CIC_5167,
|
||||
CIC_6101,
|
||||
CIC_7102,
|
||||
CIC_6102_7101,
|
||||
CIC_x103,
|
||||
CIC_x105,
|
||||
CIC_x106,
|
||||
CIC_8301,
|
||||
CIC_8302,
|
||||
CIC_8303,
|
||||
CIC_8401,
|
||||
CIC_8501,
|
||||
CIC_UNKNOWN,
|
||||
} cic_type_t;
|
||||
|
||||
|
||||
cic_type_t cic_detect (uint8_t *ipl3);
|
||||
uint8_t cic_get_seed (cic_type_t cic_type);
|
||||
|
||||
|
||||
#endif
|
@ -1,50 +0,0 @@
|
||||
#include "crc32.h"
|
||||
|
||||
|
||||
static const uint32_t crc32_table[256] = {
|
||||
0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
|
||||
0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
|
||||
0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
|
||||
0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
|
||||
0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
|
||||
0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
|
||||
0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
|
||||
0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
|
||||
0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
|
||||
0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
|
||||
0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
|
||||
0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
|
||||
0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
|
||||
0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
|
||||
0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
|
||||
0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
|
||||
0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
|
||||
0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
|
||||
0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
|
||||
0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
|
||||
0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
|
||||
0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
|
||||
0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
|
||||
0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
|
||||
0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
|
||||
0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
|
||||
0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
|
||||
0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
|
||||
0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
|
||||
0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
|
||||
0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
|
||||
0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D,
|
||||
};
|
||||
|
||||
|
||||
uint32_t crc32_calculate (void *buffer, size_t length) {
|
||||
uint32_t crc32 = 0xFFFFFFFFUL;
|
||||
|
||||
uint8_t *byte_pointer = (uint8_t *) (buffer);
|
||||
|
||||
while (length--) {
|
||||
crc32 = (crc32 >> 8) ^ crc32_table[(crc32 & 0xFF) ^ (*byte_pointer++)];
|
||||
}
|
||||
|
||||
return ~(crc32);
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
#ifndef CRC32_H__
|
||||
#define CRC32_H__
|
||||
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
uint32_t crc32_calculate (void *buffer, size_t length);
|
||||
|
||||
|
||||
#endif
|
@ -247,8 +247,6 @@ typedef struct {
|
||||
uint32_t version;
|
||||
uint32_t mem_size;
|
||||
uint8_t app_nmi_buffer[64];
|
||||
uint32_t __reserved_1[37];
|
||||
uint32_t mem_size_6105;
|
||||
} os_info_t;
|
||||
|
||||
#define OS_INFO_BASE (0x80000300UL)
|
||||
|
@ -16,7 +16,7 @@ void main (void) {
|
||||
|
||||
boot_params_t boot_params;
|
||||
|
||||
boot_params.reset_type = OS_INFO->reset_type;
|
||||
boot_params.reset_type = BOOT_RESET_TYPE_COLD;
|
||||
boot_params.tv_type = sc64_boot_params.tv_type;
|
||||
boot_params.cic_seed = (sc64_boot_params.cic_seed & 0xFF);
|
||||
boot_params.detect_cic_seed = (sc64_boot_params.cic_seed == CIC_SEED_AUTO);
|
||||
|
@ -4,22 +4,13 @@
|
||||
|
||||
#define RI_ADDRESS 0xA4700000
|
||||
|
||||
#define RI_MODE 0x00
|
||||
#define RI_CONFIG 0x04
|
||||
#define RI_CURRENT_LOAD 0x08
|
||||
#define RI_SELECT 0x0C
|
||||
#define RI_REFRESH 0x10
|
||||
#define RI_LATENCY 0x14
|
||||
|
||||
#define RI_MODE_RESET 0x00000000
|
||||
#define RI_MODE_STANDBY 0x0000000E
|
||||
|
||||
#define RDRAM_RESET_DELAY 1024
|
||||
#define RDRAM_STANDBY_DELAY 512
|
||||
|
||||
.set noat
|
||||
.section .text.reboot, "ax", %progbits
|
||||
.type reboot, %object
|
||||
|
||||
reboot_start:
|
||||
.global reboot_start
|
||||
|
||||
@ -43,39 +34,33 @@ reboot_entry:
|
||||
|
||||
li $sp, STACK_ADDRESS
|
||||
|
||||
reset_rdram:
|
||||
bnez $s5, reset_rdram_skip
|
||||
|
||||
reset_rdram:
|
||||
li $t0, RI_ADDRESS
|
||||
|
||||
li $t1, RI_MODE_RESET
|
||||
sw $t1, RI_MODE($t0)
|
||||
|
||||
li $t2, RDRAM_RESET_DELAY
|
||||
1:
|
||||
addiu $t2, (-1)
|
||||
bnez $t2, 1b
|
||||
|
||||
sw $zero, RI_CONFIG($t0)
|
||||
sw $zero, RI_CURRENT_LOAD($t0)
|
||||
sw $zero, RI_SELECT($t0)
|
||||
sw $zero, RI_REFRESH($t0)
|
||||
|
||||
li $t1, RI_MODE_STANDBY
|
||||
sw $t1, RI_MODE($t0)
|
||||
|
||||
li $t2, RDRAM_STANDBY_DELAY
|
||||
1:
|
||||
addiu $t2, (-1)
|
||||
bnez $t2, 1b
|
||||
sw $zero, RI_SELECT($t0)
|
||||
reset_rdram_skip:
|
||||
|
||||
prepare_registers:
|
||||
la $t0, ra_table
|
||||
sll $t1, $s4, 2
|
||||
add $t0, $t1
|
||||
lw $ra, ($t0)
|
||||
detect_console_region:
|
||||
li $t0, 1
|
||||
beq $s4, $zero, pal_console
|
||||
beq $s4, $t0, ntsc_console
|
||||
b mpal_console
|
||||
|
||||
pal_console:
|
||||
li $ra, 0xA4001554
|
||||
b prepare_registers
|
||||
|
||||
ntsc_console:
|
||||
li $ra, 0xA4001550
|
||||
b prepare_registers
|
||||
|
||||
mpal_console:
|
||||
li $ra, 0xA4001554
|
||||
|
||||
prepare_registers:
|
||||
move $at, $zero
|
||||
move $v0, $zero
|
||||
move $v1, $zero
|
||||
@ -85,7 +70,7 @@ prepare_registers:
|
||||
move $a3, $zero
|
||||
move $t0, $zero
|
||||
move $t1, $zero
|
||||
move $t2, $zero
|
||||
li $t2, 0x40
|
||||
move $t4, $zero
|
||||
move $t5, $zero
|
||||
move $t6, $zero
|
||||
@ -104,11 +89,5 @@ run_ipl3:
|
||||
li $t3, IPL3_ENTRY
|
||||
jr $t3
|
||||
|
||||
ra_values:
|
||||
.set ra_table, REBOOT_ADDRESS + (. - reboot_start)
|
||||
.word 0xA4001554
|
||||
.word 0xA4001550
|
||||
.word 0xA4001554
|
||||
|
||||
.set reboot_size, (. - reboot_start)
|
||||
.global reboot_size
|
||||
|
@ -2,8 +2,9 @@
|
||||
|
||||
|
||||
.section .text.rom_header, "a", %progbits
|
||||
.type rom_header, %object
|
||||
|
||||
rom_header:
|
||||
.type rom_header, %object
|
||||
|
||||
header_pi_config:
|
||||
.word 0x80371240
|
||||
@ -26,15 +27,17 @@ header_text_info:
|
||||
.org 0x40, 0x00
|
||||
|
||||
|
||||
.section .text.ipl3, "a", %progbits
|
||||
.type ipl3, %object
|
||||
.section .text.ipl3, "ax", %progbits
|
||||
|
||||
ipl3:
|
||||
.type ipl3, %function
|
||||
.incbin "header", 0x40
|
||||
|
||||
|
||||
.section .text.entry_handler, "ax", %progbits
|
||||
.type entry_handler, %function
|
||||
|
||||
entry_handler:
|
||||
.type entry_handler, %function
|
||||
.global entry_handler
|
||||
|
||||
la $gp, _gp
|
||||
|
@ -20,9 +20,9 @@ fn calculate_ipl3_checksum(ipl3: &[u8], seed: u8) -> Result<u64, Error> {
|
||||
let add = |a1: u32, a2: u32| u32::wrapping_add(a1, a2);
|
||||
let sub = |a1: u32, a2: u32| u32::wrapping_sub(a1, a2);
|
||||
let mul = |a1: u32, a2: u32| u32::wrapping_mul(a1, a2);
|
||||
let lsh = |a: u32, s: u32| if s >= 32 { 0 } else { u32::wrapping_shl(a, s) };
|
||||
let rsh = |a: u32, s: u32| if s >= 32 { 0 } else { u32::wrapping_shr(a, s) };
|
||||
let checksum = |a0: u32, a1: u32, a2: u32| {
|
||||
let rol = |a: u32, s: u32| u32::rotate_left(a, s);
|
||||
let ror = |a: u32, s: u32| u32::rotate_right(a, s);
|
||||
let sum = |a0: u32, a1: u32, a2: u32| {
|
||||
let prod = (a0 as u64).wrapping_mul(if a1 == 0 { a2 as u64 } else { a1 as u64 });
|
||||
let hi = ((prod >> 32) & 0xFFFFFFFF) as u32;
|
||||
let lo = (prod & 0xFFFFFFFF) as u32;
|
||||
@ -32,117 +32,80 @@ fn calculate_ipl3_checksum(ipl3: &[u8], seed: u8) -> Result<u64, Error> {
|
||||
|
||||
let init = add(mul(MAGIC, seed as u32), 1) ^ get(0);
|
||||
|
||||
let mut buffer = vec![init; 16];
|
||||
let mut buf = vec![init; 16];
|
||||
|
||||
for i in 1..=1008 as u32 {
|
||||
let data_prev = get(i.saturating_sub(2));
|
||||
let data_curr = get(i - 1);
|
||||
let prev = get(i.saturating_sub(2));
|
||||
let data = get(i - 1);
|
||||
|
||||
buffer[0] = add(buffer[0], checksum(sub(1007, i), data_curr, i));
|
||||
buffer[1] = checksum(buffer[1], data_curr, i);
|
||||
buffer[2] = buffer[2] ^ data_curr;
|
||||
buffer[3] = add(buffer[3], checksum(add(data_curr, 5), MAGIC, i));
|
||||
|
||||
let shift = data_prev & 0x1F;
|
||||
let data_left = lsh(data_curr, 32 - shift);
|
||||
let data_right = rsh(data_curr, shift);
|
||||
let b4_shifted = data_left | data_right;
|
||||
buffer[4] = add(buffer[4], b4_shifted);
|
||||
|
||||
let shift = rsh(data_prev, 27);
|
||||
let data_left = lsh(data_curr, shift);
|
||||
let data_right = rsh(data_curr, 32 - shift);
|
||||
let b5_shifted = data_left | data_right;
|
||||
buffer[5] = add(buffer[5], b5_shifted);
|
||||
|
||||
if data_curr < buffer[6] {
|
||||
buffer[6] = add(buffer[3], buffer[6]) ^ add(data_curr, i);
|
||||
buf[0] = add(buf[0], sum(sub(1007, i), data, i));
|
||||
buf[1] = sum(buf[1], data, i);
|
||||
buf[2] = buf[2] ^ data;
|
||||
buf[3] = add(buf[3], sum(add(data, 5), MAGIC, i));
|
||||
buf[4] = add(buf[4], ror(data, prev & 0x1F));
|
||||
buf[5] = add(buf[5], rol(data, prev >> 27));
|
||||
buf[6] = if data < buf[6] {
|
||||
add(buf[3], buf[6]) ^ add(data, i)
|
||||
} else {
|
||||
buffer[6] = add(buffer[4], data_curr) ^ buffer[6];
|
||||
}
|
||||
|
||||
let shift = data_prev & 0x1F;
|
||||
let data_left = lsh(data_curr, shift);
|
||||
let data_right = rsh(data_curr, 32 - shift);
|
||||
buffer[7] = checksum(buffer[7], data_left | data_right, i);
|
||||
|
||||
let shift = rsh(data_prev, 27);
|
||||
let data_left = lsh(data_curr, 32 - shift);
|
||||
let data_right = rsh(data_curr, shift);
|
||||
buffer[8] = checksum(buffer[8], data_left | data_right, i);
|
||||
|
||||
if data_prev < data_curr {
|
||||
buffer[9] = checksum(buffer[9], data_curr, i)
|
||||
add(buf[4], data) ^ buf[6]
|
||||
};
|
||||
buf[7] = sum(buf[7], rol(data, prev & 0x1F), i);
|
||||
buf[8] = sum(buf[8], ror(data, prev >> 27), i);
|
||||
buf[9] = if prev < data {
|
||||
sum(buf[9], data, i)
|
||||
} else {
|
||||
buffer[9] = add(buffer[9], data_curr);
|
||||
}
|
||||
add(buf[9], data)
|
||||
};
|
||||
|
||||
if i == 1008 {
|
||||
break;
|
||||
}
|
||||
|
||||
let data_next = get(i);
|
||||
let next = get(i);
|
||||
|
||||
buffer[10] = checksum(add(buffer[10], data_curr), data_next, i);
|
||||
buffer[11] = checksum(buffer[11] ^ data_curr, data_next, i);
|
||||
buffer[12] = add(buffer[12], buffer[8] ^ data_curr);
|
||||
|
||||
let shift = data_curr & 0x1F;
|
||||
let data_left = lsh(data_curr, 32 - shift);
|
||||
let data_right = rsh(data_curr, shift);
|
||||
let tmp = data_left | data_right;
|
||||
let shift = data_next & 0x1F;
|
||||
let data_left = lsh(data_next, 32 - shift);
|
||||
let data_right = rsh(data_next, shift);
|
||||
buffer[13] = add(buffer[13], add(tmp, data_left | data_right));
|
||||
|
||||
let shift = data_curr & 0x1F;
|
||||
let data_left = lsh(data_next, 32 - shift);
|
||||
let data_right = rsh(data_next, shift);
|
||||
let sum = checksum(buffer[14], b4_shifted, i);
|
||||
buffer[14] = checksum(sum, data_left | data_right, i);
|
||||
|
||||
let shift = rsh(data_curr, 27);
|
||||
let data_left = lsh(data_next, shift);
|
||||
let data_right = rsh(data_next, 32 - shift);
|
||||
let sum = checksum(buffer[15], b5_shifted, i);
|
||||
buffer[15] = checksum(sum, data_left | data_right, i);
|
||||
buf[10] = sum(add(buf[10], data), next, i);
|
||||
buf[11] = sum(buf[11] ^ data, next, i);
|
||||
buf[12] = add(buf[12], buf[8] ^ data);
|
||||
buf[13] = add(buf[13], add(ror(data, data & 0x1F), ror(next, next & 0x1F)));
|
||||
buf[14] = sum(
|
||||
sum(buf[14], ror(data, prev & 0x1F), i),
|
||||
ror(next, data & 0x1F),
|
||||
i,
|
||||
);
|
||||
buf[15] = sum(
|
||||
sum(buf[15], rol(data, prev >> 27), i),
|
||||
rol(next, data >> 27),
|
||||
i,
|
||||
);
|
||||
}
|
||||
|
||||
let mut final_buffer = vec![buffer[0]; 4];
|
||||
let mut final_buf = vec![buf[0]; 4];
|
||||
|
||||
for i in 0..16 as u32 {
|
||||
let data = buffer[i as usize];
|
||||
let data = buf[i as usize];
|
||||
|
||||
let shift = data & 0x1F;
|
||||
let data_left = lsh(data, 32 - shift);
|
||||
let data_right = rsh(data, shift);
|
||||
let b0_shifted = add(final_buffer[0], data_left | data_right);
|
||||
final_buffer[0] = b0_shifted;
|
||||
|
||||
if data < b0_shifted {
|
||||
final_buffer[1] = add(final_buffer[1], data);
|
||||
final_buf[0] = add(final_buf[0], ror(data, data & 0x1F));
|
||||
final_buf[1] = if data < final_buf[0] {
|
||||
add(final_buf[1], data)
|
||||
} else {
|
||||
final_buffer[1] = checksum(final_buffer[1], data, i);
|
||||
}
|
||||
|
||||
if rsh(data & 0x02, 1) == (data & 0x01) {
|
||||
final_buffer[2] = add(final_buffer[2], data);
|
||||
sum(final_buf[1], data, i)
|
||||
};
|
||||
final_buf[2] = if ((data & 0x02) >> 1) == (data & 0x01) {
|
||||
add(final_buf[2], data)
|
||||
} else {
|
||||
final_buffer[2] = checksum(final_buffer[2], data, i);
|
||||
}
|
||||
|
||||
if (data & 0x01) == 0x01 {
|
||||
final_buffer[3] = final_buffer[3] ^ data;
|
||||
sum(final_buf[2], data, i)
|
||||
};
|
||||
final_buf[3] = if (data & 0x01) == 0x01 {
|
||||
final_buf[3] ^ data
|
||||
} else {
|
||||
final_buffer[3] = checksum(final_buffer[3], data, i);
|
||||
}
|
||||
sum(final_buf[3], data, i)
|
||||
};
|
||||
}
|
||||
|
||||
let sum = checksum(final_buffer[0], final_buffer[1], 16);
|
||||
let xor = final_buffer[3] ^ final_buffer[2];
|
||||
let final_sum = sum(final_buf[0], final_buf[1], 16);
|
||||
let final_xor = final_buf[3] ^ final_buf[2];
|
||||
|
||||
let checksum = (((sum & 0xFFFF) as u64) << 32) | (xor as u64);
|
||||
let checksum = (((final_sum & 0xFFFF) as u64) << 32) | (final_xor as u64);
|
||||
|
||||
Ok(checksum)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user