Skip to content

Instantly share code, notes, and snippets.

@JayFoxRox
Created March 16, 2020 00:43
Show Gist options
  • Save JayFoxRox/6b2adee2ea3c5ebd164d8f6e4c4c5a8a to your computer and use it in GitHub Desktop.
Save JayFoxRox/6b2adee2ea3c5ebd164d8f6e4c4c5a8a to your computer and use it in GitHub Desktop.
Analysis of SDG605B x010 firmware
void FUN_CODE_33cd_12__handle_INQUIRY(void)
{
// EVPD must be zero
if (BYTE_INTMEM_9b & 1) {
FUN_CODE_27e2_error_tracking_probably(SPC_SK_ILLEGAL_REQUEST,0x24,0);
return;
}
// Page code must be zero
if (BYTE_INTMEM_9c != 0) {
FUN_CODE_27e2_error_tracking_probably(SPC_SK_ILLEGAL_REQUEST,0x24,0);
return;
}
// Skip empty access
if (BYTE_INTMEM_9e == 0) {
return;
}
// Clamp to 0x60 if necessary
if (BYTE_INTMEM_9e >= 0x60) {
DAT_INTMEM_8b = 0x00;
DAT_INTMEM_8c = 0x60;
} else {
DAT_INTMEM_8b = 0x00;
DAT_INTMEM_8c = BYTE_INTMEM_9e;
}
// Return the data that was written in init.c
FUN_CODE_79a4_return_data_from_master_maybe(0x200);
}
// Uses `MOV @R0,A` (ptr is R0, so 8-bit ptr.)
void FUN_CODE_1f3d(uint8_t ptr,uint32_t param_2) {
INTMEM[ptr+0] = param_2 >> 24;
INTMEM[ptr+1] = param_2 >> 16;
INTMEM[ptr+2] = param_2 >> 8;
INTMEM[ptr+3] = param_2 >> 0;
}
void FUN_CODE_4467_25__READ_CAPACITY(void)
{
byte bVar1;
byte bVar2;
char cVar3;
byte bVar4;
byte bVar5;
char cVar6;
undefined uVar7;
DAT_EXTMEM_807e &= ~0x20;
if (26.1 == 0) {
cVar3 = read_volatile_1(DAT_EXTMEM_805e);
if ((cVar3 == 0x00) || (cVar3 == 0x03)) {
write_volatile_1(DAT_EXTMEM_8010,0x10);
write_volatile_1(DAT_EXTMEM_8093,0x10);
}
DAT_EXTMEM_807f &= ~0x80;
} else {
//FIXME: Similar code is already found in the PFI read stuff for 0xAD!
if (20.4 == 0) {
// Assumption: Single-layer?
bVar1 = read_volatile_1(DAT_EXTMEM_8081);
if (bVar1 & 0x80) {
write_volatile_1(DAT_EXTMEM_8010,6);
write_volatile_1(DAT_EXTMEM_8093,6);
} else if (bVar1 & 0x40) {
write_volatile_1(DAT_EXTMEM_8010,6);
write_volatile_1(DAT_EXTMEM_8093,6);
} else {
write_volatile_1(DAT_EXTMEM_8010,6);
write_volatile_1(DAT_EXTMEM_8093,6);
}
} else {
// Assumption: Dual-layer?
write_volatile_1(DAT_EXTMEM_8010,6);
write_volatile_1(DAT_EXTMEM_8093,6);
}
}
FUN_CODE_1f3d(0x94, DAT_EXTMEM_8043804480458046 - 1); // MMIO loaded from left to right
// Set response length?
write_volatile_1(DAT_EXTMEM_4024,8);
// Write response
{
// From MMC spec:
// > The returned Logical Block Address shall be the
// > last sector in the last complete session.
// >
// > The Block Length shall be reported, in bytes, as 2048d.
// > A block length of 512 is obsolete.
// >
// > For CD media, the last logical block shall be
// > determined by converting the last recorded
// > Lead-out to an LBAand subtracting one.
// > If the resulting address points to a run out block
// > (because the session was recorded withpackets or
// > track at once in data mode), the Logical Unit shall
// > subtract 2 from the LBA to point to the actual
// > last user data block. If no complete session
// > exists on the medium, this field shall be set to zero.
// Logical Block Address
DAT_EXTMEM_4010 = DAT_INTMEM_94; // = ( DAT_EXTMEM_8043..
DAT_EXTMEM_4010 = DAT_INTMEM_95; // = ..DAT_EXTMEM_8044..
DAT_EXTMEM_4010 = DAT_INTMEM_96; // = ..DAT_EXTMEM_8045..
DAT_EXTMEM_4010 = DAT_INTMEM_97; // = ..DAT_EXTMEM_8046 ) - 1
// Block Length in Bytes
DAT_EXTMEM_4010 = 0x00;
DAT_EXTMEM_4010 = 0x00;
DAT_EXTMEM_4010 = DAT_EXTMEM_8057;
DAT_EXTMEM_4010 = DAT_EXTMEM_8058;
}
//FIXME: WTF is this?
29.6 = 1;
return;
}
// State when entering FUN_CODE_4b5e
//
// AD 00 FF02FDFF FE 00 0800 xx C0 | The SCSI ATAPI CDB
// 9a 9b 9c9d9e9f a0 a1 a2a3 a4 a5 | INTMEM_* address
// 9a | operation code (READ DVD STRUCTURE)
// 9b | ???
// 9c9d9e9f | sector number
// a0 | layer number
// a1 | format
// a2a3 | size
// a4 | "Authentication Grant ID" (AGID)
// a5 | control
//
// This feels like it might be accepted by this firmware, too:
// (Tested on 23 Jan. 2020 Does not work.. why?)
//
// AD 00 00FD0200 01 00 0800 xx 00 | The SCSI ATAPI CDB Hack
// 9c9d9e9f | 0xFF02FDFF xor 0xFFFFFFFF
// a0 | 0xFE xor 0xFF
// a5 | Anything but 0xC0
// WARNING: Expects:
// - EXTMEM_8003 (unknown)
// - INTMEM_8b8c (read length)
// - EXTMEM_80048005 (some base address [always set to zero?] - param_1 gets added)
// Uses:
// - INTMEM_8b8c (size calculation)
// - INTMEM_a6a7 (offset calculation)
//FIXME: Possibly missing volatile writes to EXTMEM
void FUN_CODE_79a4(ushort param_1) {
// If 8b8c is odd, make it even by incrementing by one
if (DAT_INTMEM_8b8c & 1) {
DAT_INTMEM_8b8c += 1;
}
DAT_INTMEM_a6a7 = DAT_EXTMEM_80048005 + param_1;
DAT_EXTMEM_4031 = DAT_EXTMEM_8003; //FIXME: unknown
DAT_EXTMEM_40324033 = DAT_INTMEM_a6a7; // read offset? [4033 is written last]
DAT_EXTMEM_40344035 = DAT_INTMEM_8b8c; // read length [4034 is written last]
29.6 = 1; //FIXME: What does this do?
return;
}
// Probably almost same inputs as FUN_CODE_79a4 [very similar]
void FUN_CODE_79de(ushort param_1) {
DAT_INTMEM_a6a7 = DAT_EXTMEM_80048005 + param_1;
DAT_EXTMEM_4031 = DAT_EXTMEM_8003; //FIXME: unknown
DAT_EXTMEM_40324033 = DAT_INTMEM_a6a7; // read offset?
DAT_EXTMEM_4036 = DAT_INTMEM_8c; // read length?
return;
}
void FUN_CODE_7966(void) {
DAT_EXTMEM_400e &= ~0x20;
DAT_EXTMEM_4012 = 0x00;
DAT_EXTMEM_4015 = 0x00;
DAT_EXTMEM_4017 = 0x50;
DAT_EXTMEM_4021 = 0x20;
DAT_EXTMEM_8000 = 0x00;
DAT_EXTMEM_8001 = 0x64;
while(!(DAT_EXTMEM_400f & 0x20)) {
if (DAT_EXTMEM_8000 != 0) { continue; }
if (DAT_EXTMEM_8001 != 0) { continue; }
break;
}
// Why u no XOR?!
DAT_EXTMEM_400e += 0x20;
return;
}
// Error handler?
void FUN_CODE_27e2(byte param_1,byte param_2,byte param_3) {
DAT_EXTMEM_8035 = param_2;
DAT_EXTMEM_8049 = param_1;
DAT_EXTMEM_805f = param_3;
return;
}
void FUN_CODE_4b5e_handle_AD__READ_DVD_STRUCTURE(void)
{
// FIXME: WTF is this shit?
byte bVar1 = read_volatile_1(DAT_EXTMEM_8080);
bVar1 |= 0x20;
write_volatile_1(DAT_EXTMEM_8080,bVar1);
bVar1 &= ~0x8;
write_volatile_1(DAT_EXTMEM_8080,bVar1);
//FIXME: WTF is this shit? (maybe check for CD or non-DVD disc?)
if (26.1 == 0) {
DAT_EXTMEM_807e |= 0x10;
FUN_CODE_27e2(2,0x30,5);
return;
}
// Handle Xbox specific SS request
if (BYTE_INTMEM_a5 == 0xC0) {
// Flip bits in sector number and layer number
BYTE_INTMEM_9c9d9e9f = ~BYTE_INTMEM_9c9d9e9f;
BYTE_INTMEM_a0 = ~BYTE_INTMEM_a0;
}
// If layer number is not 0 or 1, error?
if ((BYTE_INTMEM_a0 != 0) && (BYTE_INTMEM_a0 != 1)) {
FUN_CODE_27e2(0,0x24,5);
return;
}
// Do some extra checks for higher layers
if (BYTE_INTMEM_a0 != 0) {
// From MMC spec:
// > Requests for Format FFh shall always be fullfilled,
// > even if there is no medium or an incompatible medium installed
// Probably checks if this is a dual-layer disk (20.4?)
// If this isn't a dual layer disk, we'd have to supply 0xFF.
// Otherwise it would be considered "no media"
if ((20.4 == 0) && (BYTE_INTMEM_a1 != 0xff)) {
FUN_CODE_27e2(0,0x24,5);
return;
}
}
// Set layer number to 0 if ???
//FIXME: What's this?
if (20.5 == 0) {
BYTE_INTMEM_a0 = 0;
}
// Reduce size by 4 as we'll add a header.
// INTMEM_9c stores header size, 8b8c stores data size
if (BYTE_INTMEM_a2a3 < 4) {
BYTE_INTMEM_9c = BYTE_INTMEM_a3;
DAT_INTMEM_8b8c = 0x0000;
} else {
BYTE_INTMEM_9c = 4;
DAT_INTMEM_8b8c = BYTE_INTMEM_a2a3 - 4;
}
// Copyright
if (BYTE_INTMEM_a1 == 1) {
DAT_EXTMEM_807e |= 0x10;
write_volatile_1(DAT_EXTMEM_8034,0);
FUN_CODE_7300();
return;
}
// Disc Key
if (BYTE_INTMEM_a1 == 2) {
FUN_CODE_7341();
return;
}
// BCA
if (BYTE_INTMEM_a1 == 3) {
bVar1 = read_volatile_1(DAT_EXTMEM_8080);
if ((bVar1 & 1) == 0) {
signed char ret = FUN_CODE_a801(0xE10);
if (ret >= 0) {
FUN_CODE_27e2(0,0x24,5);
return;
}
FUN_CODE_73d0();
return;
}
bVar1 = read_volatile_1(DAT_EXTMEM_8080);
if ((bVar1 & 1) == 1) {
signed char ret = FUN_CODE_a801(0x2A10);
if (ret >= 0) {
FUN_CODE_27e2(0,0x24,5);
return;
}
FUN_CODE_73d0();
return;
}
FUN_CODE_27e2(0,0x24,5);
return;
}
// Manufacturer
if (BYTE_INTMEM_a1 == 4) {
FUN_CODE_7476();
return;
}
// Physical
if (BYTE_INTMEM_a1 == 0) {
DAT_EXTMEM_807e &= ~0x20;
// Compiler bug / bad hand-assembly?
// (All paths run the same code?)
// Something to do with dual layer?
if (20.4 == 0) {
// Assumption: Single-layer disc
bVar1 = read_volatile_1(DAT_EXTMEM_8081);
if (bVar1 & 0x80) {
write_volatile_1(DAT_EXTMEM_8010,6);
write_volatile_1(DAT_EXTMEM_8093,6);
} else if (bVar1 & 0x40) {
write_volatile_1(DAT_EXTMEM_8010,6);
write_volatile_1(DAT_EXTMEM_8093,6);
} else {
write_volatile_1(DAT_EXTMEM_8010,6);
write_volatile_1(DAT_EXTMEM_8093,6);
}
} else {
// Assumption: Dual-layer disc [feels like this should be the single layer case?]
write_volatile_1(DAT_EXTMEM_8010,6);
write_volatile_1(DAT_EXTMEM_8093,6);
}
DAT_EXTMEM_807e |= 0x10;
write_volatile_1(DAT_EXTMEM_8034,0);
FUN_CODE_728c();
return;
}
// Structure List
if (BYTE_INTMEM_a1 == 0xff) {
FUN_CODE_74b7();
return;
}
// Some error handler?
//FIXME: Check if this is SK, ASQ, ASQC
// Probably not?
FUN_CODE_27e2(0,0x24,5);
return;
}
// Physical (PFI)
void FUN_CODE_728c(void) {
// Skip if size is zero
if (DAT_INTMEM_a2a3 == 0) {
return;
}
// Handle SS requests
if (DAT_INTMEM_a5 == 0xC0) {
// Transfer header
DAT_EXTMEM_4024 = DAT_INTMEM_9c;
write_volatile_1(DAT_EXTMEM_4010,0x06); // 0x664
write_volatile_1(DAT_EXTMEM_4010,0x64);
write_volatile_1(DAT_EXTMEM_4010,0x00);
write_volatile_1(DAT_EXTMEM_4010,0x00);
// Limit the read size to allowed portion of SS
//FIXME: Ensure this is the same: if (-1 < (DAT_INTMEM_8b < 6U - (((DAT_INTMEM_8c <= 0x64) << 7) >> 7)) << 7) {
if (DAT_INTMEM_8b8c > 0x664) {
DAT_INTMEM_8b8c = 0x664;
}
FUN_CODE_79a4(0x2A00);
} else {
// Transfer header (why is this 0x802 ahd not 804?)
DAT_EXTMEM_4024 = BYTE_INTMEM_9c;
write_volatile_1(DAT_EXTMEM_4010,0x08); // 0x802
write_volatile_1(DAT_EXTMEM_4010,0x02);
write_volatile_1(DAT_EXTMEM_4010,0x00);
write_volatile_1(DAT_EXTMEM_4010,0x00);
//FIXME: Ensure this is the same: if (-1 < (DAT_INTMEM_8b < 8U - (((DAT_INTMEM_8c <= 0) << 7) >> 7)) << 7) {
if (DAT_INTMEM_8b8c > 0x800)
DAT_INTMEM_8b8c = 0x800;
}
if (DAT_INTMEM_a0 == 0) {
FUN_CODE_79a4(0xE00);
} else {
FUN_CODE_79a4(0x2A00);
}
}
}
// Manufacturer (DMI)
void FUN_CODE_7476(void) {
// Skip if read size is zero
if (BYTE_INTMEM_a2a3 == 0) {
return;
}
write_volatile_1(DAT_EXTMEM_4024,BYTE_INTMEM_9c);
write_volatile_1(DAT_EXTMEM_4010,0x08); // 0x802?
write_volatile_1(DAT_EXTMEM_4010,0x02);
write_volatile_1(DAT_EXTMEM_4010,0x00);
write_volatile_1(DAT_EXTMEM_4010,0x00);
// Clamp read size to 0x800
//FIXME: Ensure that this is the same as if (-1 < (DAT_INTMEM_8b < 8U - (((DAT_INTMEM_8c == 0x00) << 7) >> 7)) << 7) {
if (DAT_INTMEM_8b8c > 0x800) {
DAT_INTMEM_8b8c = 0x800;
}
// Differentiate target layer
if (BYTE_INTMEM_a0 == 0) {
FUN_CODE_79a4(0x1600);
} else {
FUN_CODE_79a4(0x3200);
}
}
// These are some commands I could make out:
// Unknown
//
// F2 01 ...
//
// No idea, but does stuff in >= 0xC000 region which is assumed to be MMIO for mechanical stuff
// Unknown
//
// 9a 9b 9c 9d 9e 9f a0 a1 a2 a3
// F2 02 00 00 00 00 00 00 10 02
// ## ## ##
// ## flash bank (00 is bank 0, anything else is bank 01)
// ## ## offset
// # ## must be zero
// ## ## length (must be 0x1002)
// Unknown
//
// 9a 9b 9c 9d 9e 9f a0 a1 a2 a3
// F2 03 00 00 00 00 00 00 10 02
// ## ## ##
// ## ## ## offset
// # ## must be zero
// ## ## length (must be 0x1002)
// Write flash block(s)
//
// F2 04 <INTMEM_94=unused?> <INTMEM_95=bank> <INTMEM_96_97=address> <INTMEM_88_89_8a=size>
//
// F2 04 00 01 000000 000100 should flash 0x100 bytes in bank 1 (firmware file offset 0x10000?)
//
// Goes into 0xE800 (bank1) flasher routine.
// Probably explodes if bank is not 0 (flasher unmaps itself?).
// Size will have to be a multiple of 0x100 probably.
// Not sure how data is pushed into it.
// Read RAM(?) (the one set up by init.c)
//
// F2 05 <INTMEM_9C=unused?> <INTMEM_9D_9E_9F=address> <INTMEM_A0=unused?> <INTMEM_A1=unused?> <INTMEM_A2_A3=size>
//
// XX should probably be 0x2, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80 ? (maybe also 0x3)
// F2 05 00 000000 00 00 0200 should dump ATA IDENTIFY information
// F2 05 00 000200 00 00 0060 should dump ATAPI INQUIRY information
// F2 05 00 002A00 00 00 0800 should dump SS.bin (or PFI.bin.. who the fuck knows)
//
// Size must be even, if odd it will be rounded up.
// Data returned in same style as from ATAPI INQUIRY.
// The SH-D162D flasher uses the following (none of which are found here?!):
// cmdFCSupport: FF 02 FC 00 ...
// cmdStartDownload: FF 00 01 00 ... (fw_size follows)
// cmdSupportDownload: FF 00 FF 00 ...
//
// FIXME: Analyze sfndwin or mtkflash to figure out what the old commands used to be?
// Maybe look for further handlers?
//FIXME: This function should probably have a 32-bit argument
//FIXME: Most functions in this don't parse all arguments properly. fuck ghidra meh.
void FUN_CODE_7bdd_handle_FF__vendor(void)
{
bool bVar1;
byte bVar2;
undefined uVar3;
byte bVar4;
undefined uVar5;
byte bVar6;
undefined uVar7;
byte bVar8;
uint uVar9;
char cVar10;
char cVar11;
undefined uVar12;
uint3 uVar13;
uint in_R4R5R6R7;
uint uVar14;
undefined4 uVar16;
uint32_t uVar17;
byte bVar18;
byte bVar19;
byte bVar20;
char cVar21;
byte bVar22;
DAT_INTMEM_4a = 0;
// This is interesting - it implies these handlers take an 32-bit argument of some sort?
uint uVar15 = in_R4R5R6R7 & 0xffffff00;
// FF 66 ...
// FF 06 ...
if ((BYTE_INTMEM_9b == 0x66) || (BYTE_INTMEM_9b == 0x06)) {
bVar18 = BYTE_INTMEM_9c ^ 5;
// FF 66 05
// FF 06 05
if (BYTE_INTMEM_9c == 0x05) {
bVar18 = 0x00;
uVar15 = in_R4R5R6R7 & 0xffff0000;
DAT_INTMEM_4b = 0x00;
DAT_INTMEM_4c = 0x00;
do {
bVar1 = CARRY1(*(byte *)uVar15,DAT_INTMEM_4c);
DAT_INTMEM_4c = *(byte *)uVar15 + DAT_INTMEM_4c;
DAT_INTMEM_4b -= (bVar1 << 7) >> 7;
bVar18 = (char)uVar15 + 1;
uVar14 = uVar15 & 0xffffff00 | (uint)bVar18;
if (bVar18 == 0) {
uVar14 = uVar15 & 0xffff0000 | (uint)((char)((uVar15 & 0xffffff00) >> 8) + 1) << 8;
}
bVar18 = (byte)(uVar14 >> 0x18);
uVar15 = uVar14;
} while (((byte)(uVar14 >> 8) < 0xffU - ((((char)uVar14 != -1) << 7) >> 7)) << 7 < '\0');
//FIXME: Thanks ghidra. wtf is this shit?
bVar1 = CARRY1(bCODEffff,DAT_INTMEM_4c);
DAT_INTMEM_4c = bCODEffff + DAT_INTMEM_4c;
DAT_INTMEM_4b -= (bVar1 << 7) >> 7;
FUN_CODE_01dc(bVar18);
bVar1 = CARRY1(DAT_INTMEM_99,DAT_INTMEM_4c);
DAT_INTMEM_4c = DAT_INTMEM_99 + DAT_INTMEM_4c;
DAT_INTMEM_4b = DAT_INTMEM_98 + (DAT_INTMEM_4b - ((bVar1 << 7) >> 7));
write_volatile_1(EXT_4024_data_out_length,2);
write_volatile_1(EXT_4010_write_data_out,DAT_INTMEM_4b);
write_volatile_1(EXT_4010_write_data_out,DAT_INTMEM_4c);
29.6 = 1;
uVar15 = (uint)bVar18 << 24;
FUN_CODE_27e2(0,0,0);
}
}
// FF 08 01 [terminating if EXTMEM_8080 & 1 == 0]
if ((BYTE_INTMEM_9b == 0x08) && (BYTE_INTMEM_9c == 0x01)) {
bVar18 = read_volatile_1(DAT_EXTMEM_8080);
if (bVar18 & 1) {
DAT_EXTMEM_8022 = 0x00);
DAT_EXTMEM_8023 = FUN_CODE_a801(0x2a,0x05);
DAT_EXTMEM_8024 = FUN_CODE_a801(0x2a,0x06);
DAT_EXTMEM_8025 = FUN_CODE_a801(0x2a,0x07);
DAT_EXTMEM_8060,0x00);
DAT_EXTMEM_8061 = FUN_CODE_a801(0x2a,0x0d);
DAT_EXTMEM_8062 = FUN_CODE_a801(0x2a,0x0e);
DAT_EXTMEM_8063 = FUN_CODE_a801(0x2a,0x0f);
DAT_INTMEM_8e = 0xff;
DAT_INTMEM_8f = FUN_CODE_a801(0x2a,0x09);
DAT_INTMEM_90 = FUN_CODE_a801(0x2a,0x0A);
DAT_INTMEM_91 = FUN_CODE_a801(0x2a,0x0B);
uVar12 = read_volatile_1(DAT_EXTMEM_8060);
uVar3 = read_volatile_1(DAT_EXTMEM_8061);
uVar5 = read_volatile_1(DAT_EXTMEM_8062);
uVar7 = read_volatile_1(DAT_EXTMEM_8063);
uVar16 = CONCAT31(CONCAT21(CONCAT11(uVar12,uVar3),uVar5),uVar7);
FUN_CODE_1eca(uVar12);
uVar14 = (uint)uVar16 >> 0x18;
uVar15 = (uint)uVar16 >> 0x10;
uVar9 = (uint)uVar16 >> 8;
bVar18 = (byte)uVar16;
FUN_CODE_1f24(0x8e); //FIXME: Missing arguments?
bVar19 = (byte)uVar16 - bVar18;
bVar22 = (byte)((uint)uVar16 >> 8);
bVar18 = (char)uVar9 - ((((byte)uVar16 < bVar18) << 7) >> 7);
bVar8 = (byte)((uint)uVar16 >> 0x10);
bVar2 = (char)uVar15 - (((bVar22 < bVar18) << 7) >> 7);
uVar15 = (uint)CONCAT12(bVar8 - bVar2,CONCAT11(bVar22 - bVar18,bVar19));
cVar21 = read_volatile_1(DAT_EXTMEM_8060);
bVar4 = read_volatile_1(DAT_EXTMEM_8061);
bVar6 = read_volatile_1(DAT_EXTMEM_8062);
bVar18 = read_volatile_1(DAT_EXTMEM_8063);
bVar20 = bVar18 + bVar19;
bVar18 = (char)(uVar15 >> 8) - ((CARRY1(bVar18,bVar19) << 7) >> 7);
bVar22 = (char)(uVar15 >> 0x10) - ((CARRY1(bVar6,bVar18) << 7) >> 7);
uVar15 = (uint)CONCAT12(bVar4 + bVar22,CONCAT11(bVar6 + bVar18,bVar20));
uVar17 = CONCAT13(cVar21 + (((char)((uint)uVar16 >> 0x18) -
((char)uVar14 - (((bVar8 < bVar2) << 7) >> 7))) -
((CARRY1(bVar4,bVar22) << 7) >> 7)),
CONCAT12((char)(uVar15 >> 0x10),
CONCAT11((char)(uVar15 >> 8) - (((0xfe < bVar20) << 7) >> 7),
bVar20 + 1)));
FUN_CODE_1f3d_set_intmem_at_ptr8_to_val32(0x8e,uVar17);
cVar21 = read_volatile_1(DAT_EXTMEM_8022);
cVar10 = read_volatile_1(DAT_EXTMEM_8023);
cVar11 = read_volatile_1(DAT_EXTMEM_8024);
bVar18 = read_volatile_1(DAT_EXTMEM_8025);
FUN_CODE_1f24(0x8e,cVar10,cVar11,bVar18); //FIXME: cVar21, too probably
FUN_CODE_1f49(0x8043,cVar21,
(char)(uVar17 >> 0x18) -
(cVar21 - ((((byte)(uVar17 >> 0x10) <
(byte)(cVar10 - ((((byte)(uVar17 >> 8) <
(byte)(cVar11 - ((((byte)uVar17 < bVar18) << 7) >> 7
))) << 7) >> 7))) << 7) >> 7)));
26.6 = 1;
return;
}
}
// FF
if (BYTE_INTMEM_a8 == 0) {
FUN_CODE_27e2(0,0x3a,2);
return;
}
uVar14 = uVar15 & 0xffffff00;
// FF 50
// FF 55
// FF 70
if (((BYTE_INTMEM_9b == 0x50) || (BYTE_INTMEM_9b == 0x55) || (BYTE_INTMEM_9b == 0x70))) {
FUN_CODE_27e2(0,0x20,5);
return;
}
// FF ?? ?? ?? ?? ?? ?? ?? ?? ?? AA ??
// FF ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? AA
if (((BYTE_INTMEM_a4 == 0xaa) || (BYTE_INTMEM_a5 == 0xaa))) {
FUN_CODE_27e2(0,0x20,5);
return;
}
uVar12 = (undefined)(uVar14 >> 24);
bVar18 = BYTE_INTMEM_9c ^ 0x30;
// FF ?? 30
if (BYTE_INTMEM_9c == 0x30) {
bVar18 = 0x00;
if (26.1 == 1) {
23.2 = 0;
write_volatile_1(DAT_EXTMEM_c060,0x0A);
write_volatile_1(DAT_EXTMEM_4084,0x80);
cVar21 = 0;
DAT_INTMEM_4a = 0;
DAT_INTMEM_98 = 0x00;
DAT_INTMEM_99 = 0x00;
do {
FUN_CODE_01e1(cVar21,(char)(uVar14 >> 0x18)); //FIXME: Missing arguments?
bVar18 = DAT_INTMEM_4a;
cVar21 = read_volatile_1(DAT_EXTMEM_808c);
if (cVar21 == 0) {
break;
}
uVar14 &= 0xffffff00;
cVar21 = bVar18 + 0x37;
DAT_INTMEM_4a += 1;
} while (-1 < (bVar18 < 0xc9) << 7);
// FIXME: Some MMIO magic?
write_volatile_1(DAT_EXTMEM_808f = 0x00;
cVar21 = DAT_EXTMEM_808f;
// FIXME: Thanks obama.. probably missing arguments on next call
bVar18 = read_volatile_1(DAT_EXTMEM_8090);
read_volatile(DAT_EXTMEM_8091);
// Probably writes to EXTMEM or something?
FUN_CODE_1f49(0x808f,cVar21 + (((bVar18 < 3) << 7) >> 7));
EXT_4010_write_data_out = DAT_EXTMEM_808f | 0x80;
EXT_4010_write_data_out = DAT_EXTMEM_8090;
EXT_4010_write_data_out = DAT_EXTMEM_8091;
EXT_4010_write_data_out = DAT_EXTMEM_8092;
EXT_4010_write_data_out = DAT_EXTMEM_c015;
EXT_4010_write_data_out = DAT_EXTMEM_c014;
EXT_4010_write_data_out = DAT_EXTMEM_c017;
EXT_4010_write_data_out = DAT_EXTMEM_c016;
} else {
DAT_INTMEM_98 = 0;
DAT_INTMEM_99 = 0;
23.2 = 0;
FUN_CODE_01a0(uVar12);
cVar21 = 0;
DAT_INTMEM_4a = 0;
do {
FUN_CODE_01e6(cVar21);
bVar18 = DAT_INTMEM_4a;
if (23.4 == 1) {
break;
}
uVar14 &= 0xffffff00;
DAT_INTMEM_4a += 1;
cVar21 = bVar18 + 0x9b;
} while (((bVar18 < 0x65) << 7) < 0);
EXT_4010_write_data_out = 0x00;
uVar15 = uVar14 & 0xffffff00 | (uint)DAT_INTMEM_39;
FUN_CODE_adbe((char)((uVar14 & 0xffffff00) >> 0x18));
EXT_4010_write_data_out = (char)uVar15;
uVar14 = uVar15 & 0xffffff00 | (uint)DAT_INTMEM_3a;
FUN_CODE_adbe((char)((uVar15 & 0xffffff00) >> 0x18));
EXT_4010_write_data_out = (char)uVar14;
uVar12 = DAT_INTMEM_3b;
FUN_CODE_adbe((char)(uVar14 >> 0x18)); //FIXME: Missing arguments?
EXT_4010_write_data_out = uVar12; //FIXME: Weird ordering? [setter before call]
// Endianess swap?
EXT_4010_write_data_out = DAT_EXTMEM_c015;
EXT_4010_write_data_out = DAT_EXTMEM_c014;
// Endianess swap?
EXT_4010_write_data_out = DAT_EXTMEM_c017;
EXT_4010_write_data_out = DAT_EXTMEM_c016;
}
//FIXME: Interesting! So this can also be set later!
write_volatile_1(EXT_4024_data_out_length,8);
//FIXME: Is this a busy / ready flag maybe?
29.6 = 1;
return;
}
// FF ?? BB ...
// FF ?? FB
if ((BYTE_INTMEM_9c == 0xbb) || (BYTE_INTMEM_9c == 0xfb)) {
28.6 = 0;
write_volatile_1(DAT_EXTMEM_803e,0);
// FF ?? BB ...
if (BYTE_INTMEM_9c == 0xbb) {
// FF ?? BB 00
if (BYTE_INTMEM_9d == 0) {
FUN_CODE_01d2(uVar12);
26.0 = 0;
28.6 = 1;
return;
}
BYTE_INTMEM_a1 = BYTE_INTMEM_9d;
}
//FIXME: !!!! These are jumptable handlers! everything after this might be broken
if (26.1 == 0) {
FUN_CODE_1f9f(BYTE_INTMEM_a1,uVar12);
} else {
FUN_CODE_1f9f(BYTE_INTMEM_a1,uVar12);
}
}
//FIXME: ------------------------------ Potentially broken from here because of jumptables
... This used to be part of the previous scope.. which no longer exists ...
This function needs to be rewritten (essentially) from scratch.
write_volatile_1(DAT_EXTMEM_40b8,EXT_MEM_0x803e); //FIXME: The second argument came from `undefined *puVar23;` (why ptr?)
uVar12 = read_volatile_1(EXT_4010_write_data_out);
write_volatile_1(DAT_EXTMEM_40b9,uVar12);
do {
bVar18 = read_volatile_1(DAT_EXTMEM_40c0);
} while ((bVar18 & 3) != 1);
write_volatile_1(DAT_EXTMEM_8029,2);
return;
}
uVar13 = (uint3)(uVar14 >> 8);
// FF ?? F1
if (BYTE_INTMEM_9c == 0xf1) {
28.6 = 0;
if (26.1 == 0) {
write_volatile_1(DAT_EXTMEM_8093,0x30);
uVar12 = (undefined)(((uint)uVar13 << 8) >> 0x18);
FUN_CODE_ec24(uVar12);
write_volatile_1(DAT_EXTMEM_c006,1);
DAT_INTMEM_5d = 0;
FUN_CODE_0196(2,uVar12);
write_volatile_1(DAT_EXTMEM_c006,0);
} else {
write_volatile_1(DAT_EXTMEM_8093,0x10);
uVar12 = (undefined)(((uint)uVar13 << 8) >> 0x18);
FUN_CODE_ec24(uVar12);
write_volatile_1(DAT_EXTMEM_803d,0);
write_volatile_1(DAT_EXTMEM_c006,1);
DAT_INTMEM_5d = 0;
FUN_CODE_0196(0,uVar12);
write_volatile_1(DAT_EXTMEM_c006,0);
}
27.2 = 1;
26.0 = 1;
DAT_INTMEM_99 = 0;
DAT_INTMEM_98 = 0;
write_volatile_1(DAT_EXTMEM_4084,9);
27.0 = 0;
if (DAT_INTMEM_92 != 0x12) {
FUN_CODE_ab79();
}
FUN_CODE_018c();
DAT_INTMEM_98 = 0;
DAT_INTMEM_99 = 0;
return;
}
// FF ?? 22
if (BYTE_INTMEM_9c == 0x22) {
// FF ?? 22 00
if (BYTE_INTMEM_9d == 0) {
FUN_CODE_01eb((char)(((uint)uVar13 << 8) >> 0x18));
return;
}
// FF ?? 22 FF
if (BYTE_INTMEM_9d == 0xff) {
// FF ?? 22 FF 6E
if (BYTE_INTMEM_9e == 0x6e) {
DAT_EXTMEM_c031 &= ~(0xC0 | 0x8);
DAT_EXTMEM_c039 = DAT_EXTMEM_80ad | 4 | 1;
DAT_EXTMEM_c0b0 = 0x00;
DAT_EXTMEM_c0ef = 0x00;
}
FUN_CODE_01aa((char)(((uint)uVar13 << 8) >> 24));
DAT_INTMEM_4a = 0;
do {
bVar22 = 0x80 + EXTMEM[0xC000 | BYTE_INTMEM_9e];
bVar18 = bVar22 + DAT_INTMEM_4c;
int x = DAT_INTMEM_4b - ((CARRY1(bVar22,DAT_INTMEM_4c) << 7) >> 7);
DAT_INTMEM_4c += bVar22;
DAT_INTMEM_4b = (0x80 <= EXTMEM[0xC000 | BYTE_INTMEM_9e]) + x;
DAT_INTMEM_4a += 1;
} while (DAT_INTMEM_4a != 100);
FUN_CODE_1d0c(0);
// FF ?? 22 FF 6E
if (BYTE_INTMEM_9e == 0x6e) {
write_volatile_1(DAT_EXTMEM_c0ef,1);
}
write_volatile_1(EXT_4024_data_out_length,2);
write_volatile_1(EXT_4010_write_data_out,bVar18);
write_volatile_1(EXT_4010_write_data_out,0);
DAT_INTMEM_4a = bVar18;
29.6 = 1;
return;
}
return;
}
// FF ?? 33
if (BYTE_INTMEM_9c == 0x33) {
// FF ?? 33 00
if (BYTE_INTMEM_9d == 0) {
// FF ?? 33 00 ?? ?? ?? ?? ?? 01
if (BYTE_INTMEM_a3 == 0x01) {
DAT_INTMEM_4a = 0x00;
DAT_INTMEM_4b = 0x00;
DAT_INTMEM_4c = 0x1e;
// FF ?? 33 00 ?? ?? ?? ?? ?? 02
} else if (BYTE_INTMEM_a3 == 0x02) {
DAT_INTMEM_4a = 0x1e;
DAT_INTMEM_4b = 0x00;
DAT_INTMEM_4c = 0x3c;
// FF ?? 33 00 ?? ?? ?? ?? ?? 03
} else if (BYTE_INTMEM_a3 == 0x03) {
DAT_INTMEM_4a = 0x3c;
DAT_INTMEM_4b = 0x00;
DAT_INTMEM_4c = 0x5a;
// FF ?? 33 00 ?? ?? ?? ?? ?? 04
} else if (BYTE_INTMEM_a3 == 0x04) {
DAT_INTMEM_4a = 0x5a;
DAT_INTMEM_4b = 0x00;
DAT_INTMEM_4c = 0x78;
// FF ?? 33 00 ?? ?? ?? ?? ?? 05
} else if (BYTE_INTMEM_a3 == 0x05) {
DAT_INTMEM_4a = 0x78;
DAT_INTMEM_4b = 0x00;
DAT_INTMEM_4c = 0x80;
// FF ?? 33 00 ?? ?? ?? ?? ?? ??
} else {
uVar14 = uVar15 & 0xff000000;
FUN_CODE_27e2(0,0x24,5);
}
while (true) {
cVar21 = DAT_INTMEM_4b - (((DAT_INTMEM_4a < DAT_INTMEM_4c) << 7) >> 7);
if (((cVar21 != 0) << 7) >= 0) {
break;
}
uVar15 = uVar14 & 0xffffff00;
uVar14 = uVar15 | DAT_INTMEM_4a;
FUN_CODE_01f0(-cVar21,(char)(uVar15 >> 0x18));
write_volatile_1(EXT_4010_write_data_out,(char)uVar14);
DAT_INTMEM_4a += 1;
}
write_volatile_1(EXT_4024_data_out_length,0x1e);
29.6 = 1;
return;
}
return;
}
// Error handling
// 5 = SPC_SK_ILLEGAL_REQUEST [from sg_utils.. why can't I find this in the spec?] ?
// sg_utils also does: if ((0x20 == ssh.asc) && (0x0 == ssh.ascq)) { ret = SG_LIB_CAT_INVALID_OP; }
// So this is almost certainly: set_error(ASCQ, ASC, SK);
FUN_CODE_27e2(0,0x20,5);
return;
}
// Some BCD (4 bit) to decimal
// Converts 0x88 to 88
// Converts 0x10 to 10
byte FUN_CODE_adbe_HEX_to_DEC(byte param_1) {
return (param_1 >> 4) * 10 + (param_1 & 0xf);
}
undefined1 * FUN_CODE_1f85_copy_byte_and_return_advanced_dst_ptr(undefined1 *src,undefined1 *dst) {
*dst = *src;
return dst + 1;
}
// Actually part of the ATA function
//FIXME: Missing a bunch of code
void FUN_CODE_2446_find_some_command_handlers(byte param_1) {
byte bVar1;
char cVar2;
// INQUIRY
if (9A_cdb_operation_code == 0x12) {
FUN_CODE_27e2_error_tracking_probably(SPC_SK_NO_SENSE,0,0);
FUN_CODE_33cd();
return;
}
// GET CONFIGURATION
if (9A_cdb_operation_code == 0x46) {
FUN_CODE_27e2_error_tracking_probably(SPC_SK_ILLEGAL_REQUEST,0x24,0);
return;
}
// GET EVENT STATUS NOTIFICATION
if (9A_cdb_operation_code == 0x4a) {
FUN_CODE_27e2_error_tracking_probably(SPC_SK_ILLEGAL_REQUEST,0x24,0);
return;
}
// REQUEST SENSE
if (9A_cdb_operation_code == 0x03) {
FUN_CODE_552f();
return;
}
if (29.2 == 1) {
29.2 = 0;
2a.5 = 0;
FUN_CODE_27e2_error_tracking_probably(SPC_SK_UNIT_ATTENTION,0x29,0);
return;
}
// START STOP UNIT
if (9A_cdb_operation_code == 0x1b) {
// 00 = 0/4
// 01 = 1/5
// 10 = 2/6 LOEJ
// 11 = 3/7 LOEJ+START
// 1xx = NO_FLUSH
// 1xxx = Reserved
// ####xxxx = Power condition
// Check if only LOEJ is set = Eject
if (BYTE_INTMEM_9e == 2) {
2a.5 = 0;
FUN_CODE_27e2_error_tracking_probably(SPC_SK_NO_SENSE,0,0);
}
bool c1 = FUN_CODE_015a();
if (c1) {
// Check if only LOEJ + START are set = Load
if (BYTE_INTMEM_9e == 3) {
FUN_CODE_27e2_error_tracking_probably(SPC_SK_NO_SENSE,0,0);
return;
}
}
bool c2 = FUN_CODE_015f();
if (c2) {
// Check if only LOEJ is set = Eject
if (BYTE_INTMEM_9e == 2) {
FUN_CODE_27e2_error_tracking_probably(SPC_SK_NO_SENSE,0,0);
return;
}
}
}
// If this is not PREVENT ALLOW MEDIUM REMOVAL, do some extra stuff
// FIXME: Why is this special?
if (9A_cdb_operation_code != 0x1e) {
if (2a.5 == 1) {
2a.5 = 0;
FUN_CODE_27e2_error_tracking_probably(SPC_SK_UNIT_ATTENTION,0x28,0);
return;
}
}
bool a = (9A_cdb_operation_code == 0x1e) || // PREVENT ALLOW MEDIUM REMOVAL
(9A_cdb_operation_code == 0x5a) || // MODE SENSE (10)
(9A_cdb_operation_code == 0x55) || // MODE SELECT (10)
(9A_cdb_operation_code == 0xbd) || // MECHANISM STATUS
(9A_cdb_operation_code == 0x1b); // START STOP UNIT
bool c = (9A_cdb_operation_code == 0xa3) && ((BYTE_INTMEM_a4 & 0x3f) == 6); // SEND KEY with ???
bool b = (9A_cdb_operation_code == 0xa4) && ((BYTE_INTMEM_a4 & 0x3f) == 8); // REPORT KEY with ???
bool d = (9A_cdb_operation_code == 0xff) || // Vendor specific
(9A_cdb_operation_code == 0x23) || // READ FORMAT CAPACITIES
(9A_cdb_operation_code == 0x46); // GET CONFIGURATION
if (a || b || c || d) {
goto LAB_CODE_2572;
} else {
if (BYTE_INTMEM_a8 == 0) {
bVar1 = read_volatile_1(DAT_EXTMEM_8050);
if ((bVar1 >> 6 & 1) != 1) {
FUN_CODE_27e2_error_tracking_probably(SPC_SK_NOT_READY,0x3a,0);
return;
}
}
cVar2 = read_volatile_1(DAT_EXTMEM_8026);
if (cVar2 != 0) {
write_volatile_1(DAT_EXTMEM_8026,0);
}
cVar2 = read_volatile_1(DAT_EXTMEM_8037);
if ((cVar2 != 1) && (9A_cdb_operation_code != 0)) {
DAT_EXTMEM_8081 |= 0x8;
FUN_CODE_01a5();
DAT_EXTMEM_8081 &= ~0x8;
2c.5 = 0;
FUN_CODE_abe6(1);
}
}
LAB_CODE_2572:
FUN_CODE_27e2_error_tracking_probably(SPC_SK_NO_SENSE,0,0);
// READ (10)
if (9A_cdb_operation_code == 0x28) {
2c.4 = 0;
FUN_CODE_420e();
return;
}
// READ (12)
if (9A_cdb_operation_code == 0xa8) {
2c.4 = 1;
FUN_CODE_420e();
return;
}
// READ CD
if (9A_cdb_operation_code == 0xbe) {
FUN_CODE_4518();
return;
}
// D5=???
// READ CD MSF
if ((9A_cdb_operation_code == 0xd5) ||
(9A_cdb_operation_code == 0xb9)) {
FUN_CODE_47e2();
return;
}
/* WARNING: Subroutine does not return */
//FIXME: This is the instruction after the call into the handler.
// So the return address is the jump table address!
// Reflect using switch/case?
void* jumptable = 0x25b1; // CODE:25b1
#if 0
{
CODE:2666: handle_00h__TEST UNIT READY # table entry at CODE:0x25B1
CODE:266A: handle_01h__??? # table entry at CODE:0x25B4
CODE:2662: handle_1Bh__START STOP UNIT # table entry at CODE:0x25B7
CODE:267B: handle_1Eh__PREVENT ALLOW MEDIUM REMOVAL # table entry at CODE:0x25BA
CODE:2632: handle_23h__READ FORMAT CAPACITIES # table entry at CODE:0x25BD
CODE:2626: handle_25h__READ CAPACITY # table entry at CODE:0x25C0
CODE:264E: handle_2Bh__SEEK (10) # table entry at CODE:0x25C3
CODE:263A: handle_42h__??? # table entry at CODE:0x25C6
CODE:263E: handle_43h__READ TOC/PMA/ATIP # table entry at CODE:0x25C9
CODE:2636: handle_44h__??? # table entry at CODE:0x25CC
CODE:2612: handle_45h__??? # table entry at CODE:0x25CF
CODE:261E: handle_47h__??? # table entry at CODE:0x25D2
CODE:260E: handle_4Bh__??? # table entry at CODE:0x25D5
CODE:265E: handle_4Eh__??? # table entry at CODE:0x25D8
CODE:262A: handle_51h__READ DISC INFORMATION # table entry at CODE:0x25DB
CODE:2642: handle_52h__READ TRACK INFORMATION # table entry at CODE:0x25DE
CODE:2606: handle_55h__MODE SELECT (10) # table entry at CODE:0x25E1
CODE:260A: handle_5Ah__MODE SENSE (10) # table entry at CODE:0x25E4
CODE:2652: handle_A3h__SEND KEY # table entry at CODE:0x25E7
CODE:2646: handle_A4h__REPORT KEY # table entry at CODE:0x25EA
CODE:2618: handle_A5h__??? # table entry at CODE:0x25ED
CODE:2656: handle_A7h__SET READ AHEAD # table entry at CODE:0x25F0
CODE:262E: handle_ADh__READ DISC STRUCTURE # table entry at CODE:0x25F3
CODE:264A: handle_BAh__??? # table entry at CODE:0x25F6
CODE:265A: handle_BBh__SET CD SPEED # table entry at CODE:0x25F9
CODE:2622: handle_BDh__MECHANISM STATUS # table entry at CODE:0x25FC
CODE:266E: handle_FFh__??? # table entry at CODE:0x25FF
}
#endif
FUN_CODE_1f9f_command_handler_jumptable_acceptor(9A_cdb_operation_code,jumptable);
return;
}
// This stuff is in bank1
#define BUSY_WAIT() { \
uint8_t tmp; \
do { \
tmp = read_volatile_1(DAT_EXTMEM_4000); \
} while (tmp & 0x80); \
}
// CODE:ec00
typedef union {
uint8_t b[4];
struct {
uint16_t chip_id;
uint8_t block_erase; //FIXME: maybe?
uint8_t block_size; //FIXME: maybe?
};
} FlashType;
FlashType flash_types[8] = {
{ 0xDAC1, 0x00,0x00 }, // AE29F1008,
// W29C010, W29C011,
// W29EE010, W29EE011, W29EE012
{ 0x1FD5, 0x00,0x00 }, // AT29C010A
{ 0xBFB5, 0x01,0x10 }, // SST39SF010A
{ 0xBFD5, 0x01,0x10 }, // SST39VF010
{ 0x0120, 0x01,0x40 }, // AM29F010, AM29F010B, NX29F010, TMS29F010
{ 0x1F05, 0x01,0x20 }, // AT49BV001, AT49BV001A, AT49BV001AN, AT49BV001N,
// AT49F001, AT49F001A, AT49F001AN, AT49F001N
// AT49LV001, AT49LV001N
{ 0x374C, 0x01,0x00 }, // A29001U, A290011U
{ 0x37A1, 0x01,0x00 }, // A29001T, A290011T, A29512A
// Followed by 0xFFFF
};
static inline void flash_type1(uint8_t bVar6) {
//FIXME: Isn't this always true? bVar6 is also 0x100 aligned.
// Shouldn't these always match?
// Would only be relevant if it's misaligned in the beginning.
assert(DAT_INTMEM_97 == 0)
// If we are in the first byte of a 0x100 block, we also have to erase the chip
if (DAT_INTMEM_97 == 0) {
bVar8 = flash_types[bVar2].b[3];
// If block size is smaller than 0x100, then check our offset in small block
if (bVar8 != 0) {
bVar8 = DAT_INTMEM_96 % bVar8;
}
if (bVar8 == 0) {
// Flash Chip Erase
write_volatile_1(DAT_EXTMEM_5555,0xaa);
write_volatile_1(DAT_EXTMEM_2aaa,0x55);
write_volatile_1(DAT_EXTMEM_5555,0x80);
write_volatile_1(DAT_EXTMEM_5555,0xaa);
write_volatile_1(DAT_EXTMEM_2aaa,0x55);
*(undefined *)((ushort)DAT_INTMEM_96 << 8) = 0x30;
// Check if completed?
while ((*(byte *)((ushort)DAT_INTMEM_96 << 8) & 0x80) != 0x80);
}
}
// Appears to write 256 bytes?! (aligns bVar6 to next 0x100 boundary)
for(int i = 0; i < 0x100; i++) {
// Flash Byte Program
write_volatile_1(DAT_EXTMEM_5555,0xaa);
write_volatile_1(DAT_EXTMEM_2aaa,0x55);
write_volatile_1(DAT_EXTMEM_5555,0xa0);
BUSY_WAIT();
bVar8 = read_volatile_1(DAT_EXTMEM_400c);
*(byte*)(DAT_INTMEM_96_97 + bVar6) = bVar8;
while ((bVar8 & 0x80) != (*(byte *)(DAT_INTMEM_96_97 + bVar6) & 0x80));
bVar6 += 1;
}
assert(bVar6 == 0x00);
return bVar6;
}
// 128-byte sector based programming; from https://media.digikey.com/pdf/Data%20Sheets/Atmel%20PDFs/AT29C010A.pdf
//
// > Reprogramming the AT29C010A is performed on a sector basis;
// > 128 bytes of data are loadedinto the device and then simultaneously
// > programmed.
// >
// > During a reprogram cycle, the address locations and 128 bytes of data
// > are internally latched, freeing the address and data bus for other
// > operations.
// > Following the initiation ofa program cycle, the device will
// > automatically erase the sector and then program the latched data using
// > an internal control timer.
// > The end of a program cycle can be detected by DATA polling of I/O7.
// > Once the end of a program cycle has been detected, a new access for a
// > read or program can begin.
//
static inline uint8_t flash_type_non1(uint8_t bVar6) {
// Appears to write 256 bytes?! (aligns bVar6 to next 0x100 boundary)
for (int loop = 0; loop < 2; loop++) {
// Flash Byte Program
write_volatile_1(DAT_EXTMEM_5555,0xaa);
write_volatile_1(DAT_EXTMEM_2aaa,0x55);
write_volatile_1(DAT_EXTMEM_5555,0xa0);
// Appears to write 128 bytes?! (aligns bVar6 to next 0x80 boundary)
for(int i = 0; i < 0x80; i++) {
BUSY_WAIT();
bVar1 = read_volatile_1(DAT_EXTMEM_400c);
*(byte*)(DAT_INTMEM_96_97 + bVar6) = bVar1;
bVar6++;
}
assert(bVar6 == 0x80);
// Check if the last byte was written?
while ((bVar1 & 0x80) != (*(byte *)(DAT_INTMEM_96_97 + bVar6) & 0x80));
}
assert(bVar6 == 0x00);
return bVar6;
}
// Spin-loop to waste CPU cycles
static inline void spin() {
volatile uint16_t cVar34 = 0x0000;
do {
volatile uint8_t cVar7 = 0x00;
while (cVar7++ != 32);
cVar34 += 1;
} while(cVar34 < 0xFFFF);
}
// bank1
//FIXME: Missing all volatile writes to SFR-bits
void UndefinedFunction_e800(void) {
byte bVar1;
byte bVar2;
char cVar4;
char cVar5;
byte bVar6;
char cVar7;
byte bVar8;
byte bVar9;
// Flash Product ID Entry
write_volatile_1(DAT_EXTMEM_5555,0xaa);
write_volatile_1(DAT_EXTMEM_2aaa,0x55);
write_volatile_1(DAT_EXTMEM_5555,0x90);
// Read product ID?
//FIXME: Probably some JEDEC standard
cVar5 = read_volatile_1(UNK_EXTMEM_0000);
DAT_INTMEM_51 = read_volatile_1(UNK_EXTMEM_0001);
// Flash Product ID Exit
write_volatile_1(DAT_EXTMEM_5555,0xaa);
write_volatile_1(DAT_EXTMEM_2aaa,0x55);
write_volatile_1(DAT_EXTMEM_5555,0xf0);
// Look for this flash in the list of flashes
for(int i = 0; i < 8; i++) {
if (flash_types[i].b[0] == cVar5) && (flash_types[i].b[1] == DAT_INTMEM_51) {
break;
}
}
// Remember which entry we matched
bVar2 = i;
BUSY_WAIT();
//FIXME: Set some address
write_volatile_1(DAT_EXTMEM_4005,0x03);
write_volatile_1(DAT_EXTMEM_4006,0x33);
write_volatile_1(DAT_EXTMEM_4007,0x00);
// Write back flash information *somewhere*
write_volatile_1(DAT_EXTMEM_400c,0x33);
write_volatile_1(DAT_EXTMEM_400c,bVar2); // flash type index
write_volatile_1(DAT_EXTMEM_400c,cVar5); // product_id[0]
write_volatile_1(DAT_EXTMEM_400c,DAT_INTMEM_51); // product_id[0]
write_volatile_1(DAT_EXTMEM_400c,0x33);
// If we found a known flash
if (bVar2 < 8) {
// Set offset to write in block to zero
bVar6 = 0;
// Main writer loop which allows up to 100 retries
DAT_INTMEM_51 = 0;
while(DAT_INTMEM_51 <= 100) {
// Stop if we ran out of data to process
if (DAT_INTMEM_88_89_8a == 0) {
break;
}
// Bank select for flash write
//FIXME: This code is not mirrored in bank0.
// Wouldn't the flasher crash because it removes its own code?
if (DAT_INTMEM_95 == 0) {
P1.0 = 0;
} else {
P1.0 = 1;
}
BUSY_WAIT();
// Set address for writing
write_volatile_1(DAT_EXTMEM_4007,DAT_INTMEM_97);
write_volatile_1(DAT_EXTMEM_4006,DAT_INTMEM_96);
write_volatile_1(DAT_EXTMEM_4005,DAT_INTMEM_95);
// Block based flash or not?
if (flash_types[bVar2].b[2] == 0x01) {
bVar6 = flash_type1(bVar6);
} else {
bVar6 = flash_type_non1(bVar6);
}
BUSY_WAIT();
// Set address for readback
write_volatile_1(DAT_EXTMEM_4007,DAT_INTMEM_97);
write_volatile_1(DAT_EXTMEM_4006,DAT_INTMEM_96);
write_volatile_1(DAT_EXTMEM_4005,DAT_INTMEM_95);
// Verify the block was written successfully
while( true ) {
BUSY_WAIT();
cVar5 = read_volatile_1(DAT_EXTMEM_400c);
if (*(char*)(DAT_INTMEM_96_97 + bVar6) != cVar5) {
// Increase error count and retry
DAT_INTMEM_51 += 1;
break;
}
bVar6 += 1;
// if we reached the end of a 0x100 block..
if (bVar6 == 0) {
//FIXME: Missing wrap into _95 / _88 and overflow?
DAT_INTMEM_95_96_97 += 0x100;
DAT_INTMEM_88_89_8a -= 0x100;
break;
}
}
}
}
//FIXME: What is this?
P1.5 = 1;
if (27.5 != 0) {
27.5 = 0;
write_volatile_1(DAT_EXTMEM_4002,0x80);
if (DAT_INTMEM_51 <= 100) {
// Flash OK
write_volatile_1(DAT_EXTMEM_401b,0x50);
write_volatile_1(DAT_EXTMEM_4011,0x54);
} else {
// Too many errors
write_volatile_1(DAT_EXTMEM_401b,0x51);
write_volatile_1(DAT_EXTMEM_4011,0x54);
}
write_volatile_1(DAT_EXTMEM_4014,0);
write_volatile_1(DAT_EXTMEM_4015,0);
write_volatile_1(DAT_EXTMEM_4021,8);
}
if (DAT_INTMEM_51 <= 100) {
// Flash OK
for(int i = 0; i < 6; i++) {
write_volatile_1(DAT_EXTMEM_c006,1);
spin();
write_volatile_1(DAT_EXTMEM_c006,0);
spin();
}
} else {
// Too many errors
write_volatile_1(DAT_EXTMEM_c006,0);
}
P1.6 = 1;
write_volatile_1(DAT_EXTMEM_403b,0);
write_volatile_1(DAT_EXTMEM_c020,0);
write_volatile_1(DAT_EXTMEM_c079,0);
thunk_FUN_CODE_002e();
}
//Note: These inline functions do not exist in the actual code!
static inline void busy_loop(void) {
byte cVar7
do {
cVar7 = read_volatile_1(4000_master_status);
} while (cVar7 & 0x80);
}
// src is an EXTMEM offset
static inline uint8_t copy(const uint8_t a, const uint8_t b, uint8_t* src) {
INTMEM_4e_loop_counter_lo = a;
do {
busy_loop();
write_volatile_1(400c_master_data, src[INTMEM_4e_loop_counter_lo]);
INTMEM_4e_loop_counter_lo++;
} while(INTMEM_4e_loop_counter_lo != b)
return INTMEM_4e_loop_counter_lo;
}
static inline uint8_t set(const uint8_t a, const uint8_t b, uint8_t value) {
INTMEM_4e_loop_counter_lo = a;
do {
busy_loop();
write_volatile_1(400c_master_data, value);
INTMEM_4e_loop_counter_lo++;
} while (INTMEM_4e_loop_counter_lo != b);
return INTMEM_4e_loop_counter_lo;
}
void FUN_CODE_9e9d_initialize_some_buffered_values(void) {
// 0x0 - 0x1FF
FUN_CODE_a7bf_master_skip16_and_write8(identify_data_start._0_1_,0);
copy(0x01, 0xBE, &identify_data_start); //FIXME: add addr of identify data
set(0xBE, 0x100, 0x00);
set(0x00, 0x100, 0x00);
// 0x200 - 0x25F ...
HIFLG.2 = FUN_CODE_a7bf_master_skip16_and_write8(1701_inquiry_data,0x200);
copy(0x01, 0x60, &1701_inquiry_data);
// ... 0x260 - 0x2EF
// ... 0x2F0 - 0x37F
for(int i = 0; i < 2; i++) {
copy(0x00, 0x0C, &BYTE_ARRAY_CODE_1761);
copy(0x00, 0x08, &BYTE_ARRAY_CODE_176D);
copy(0x00, 0x10, &BYTE_ARRAY_CODE_1775);
copy(0x00, 0x1C, &BYTE_ARRAY_CODE_1785);
copy(0x00, 0x0C, &BYTE_ARRAY_CODE_17A1);
copy(0x00, 0x0A, &BYTE_ARRAY_CODE_17AD);
copy(0x00, 0x0C, &BYTE_ARRAY_CODE_17B7);
copy(0x00, 0x1A, &BYTE_ARRAY_CODE_17C3);
copy(0x00, 0x14, &auth_page_look_alike_contest_winner); //FIXME: Add address
}
unsigned uVar2 = read_volatile_1(DAT_EXTMEM_8002);
char cVar6 = read_volatile_1(DAT_EXTMEM_8003);
byte bVar3 = read_volatile_1(DAT_EXTMEM_8004);
unsigned uVar4 = read_volatile_1(DAT_EXTMEM_8005);
// Looks like DAT_INTMEM_8b8c = FUN_CODE_1efe(DAT_EXTMEM_8002800380048005 + 0x4300, 0x0A)
uVar5 = FUN_CODE_1efe(CONCAT13(uVar2,CONCAT12(cVar6 - (((0xbc < bVar3) << 7) >> 7), CONCAT11(bVar3 + 0x43,uVar4))),10);
DAT_INTMEM_8b = (byte)((ushort)uVar5 >> 8);
DAT_INTMEM_8c = (byte)uVar5;
// 0x2CE - 0x2CF (in previous array [0] offset 0x6E)
FUN_CODE_a7bf_master_skip16_and_write8(DAT_INTMEM_8b,0x2ce);
FUN_CODE_a7bf_master_skip16_and_write8(DAT_INTMEM_8c,0x2cf);
// 0x35E - 0x35F (in previous array [1] offset 0x6E)
FUN_CODE_a7bf_master_skip16_and_write8(DAT_INTMEM_8b,0x35e);
FUN_CODE_a7bf_master_skip16_and_write8(DAT_INTMEM_8c,0x35f);
// 0x380 - 0x40F
// Note: Part [2] of previous arrays!
// Offset 0x6E would be at 0x3EE - 0x3EF (not written?)
FUN_CODE_a7bf_master_skip16_and_write8(DAT_CODE_17f1,0x380);
copy(0x01, 0x0C, &DAT_CODE_17f1);
copy(0x00, 0x08, &DAT_CODE_17fd);
copy(0x00, 0x10, &DAT_CODE_1805);
copy(0x00, 0x1C, &SUB_CODE_1815);
copy(0x00, 0x0C, &DAT_CODE_1831);
copy(0x00, 0x0A, &DAT_CODE_183d);
copy(0x00, 0x0C, &DAT_CODE_1847);
copy(0x00, 0x1A, &DAT_CODE_1853);
copy(0x00, 0x14, &DAT_CODE_186d);
// 0x410 - 0x417
FUN_CODE_a7bf_master_skip16_and_write8(0,0x410);
set(0x01, 0x08, 0x00);
// 0x418 - 0x46F
HIFLG.2 = FUN_CODE_a7bf_master_skip16_and_write8(DAT_CODE_1881,0x418);
copy(0x01, 0x58, &DAT_CODE_1881);
return;
}
// This is a misnomer. I'm not sure how to call it properly though.
// Changing it now is tricky as I use master in some files already.
void FUN_CODE_79a4_return_data_from_master_maybe(ushort param_1) {
// Calculate target address
BYTE_INTMEM_a6_a7 = DAT_EXTMEM_8004_8005 + param_1; // 8005 is loaded first
// Write some address
DAT_EXTMEM_4031 = DAT_EXTMEM_8003;
DAT_EXTMEM_4032 = BYTE_INTMEM_a6;
DAT_EXTMEM_4033 = BYTE_INTMEM_a7;
// If 8b8c is odd, make it even (round up)
DAT_INTMEM_8b8c += DAT_INTMEM_8b8c & 1;
// Write length for DMA?
write_volatile_1(DAT_EXTMEM_4035_dma_out_count_lo_maybe,DAT_INTMEM_8c);
write_volatile_1(DAT_EXTMEM_4034_dma_out_count_hi_exec_maybe,DAT_INTMEM_8b);
// Enable DMA? Or maybe something unrelated?
29.6_dma_out_enable_maybe = 1;
return;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment