forked from abandoned-cocoon/firered
-
Notifications
You must be signed in to change notification settings - Fork 0
/
flash.c
127 lines (114 loc) · 2.93 KB
/
flash.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
struct flash_chip_metrics {
u32 num_bytes;
u32 block_size;
u8 block_shift;
u8 __unused1;
u16 num_blocks;
u32 __unused2;
u16 waitcnt_or;
u16 unknown1;
u16 flash_chip_id;
u16 unknown2;
};
struct flash_chip_interface {
void (*unknown_func)();
void (*write_block)(); // Wrong signature
void (*erase_all)(); // Wrong signature
void (*erase_block)(); // Wrong signature
void (*verify)(); // Wrong signature
void *unknown;
struct flash_chip_metrics metrics;
};
// TODO
void sub_81DEFA4(); // Wrong signature
void flash_write_block(); // Wrong signature
void flash_erase_all(); // Wrong signature
void flash_erase_block(); // Wrong signature
void flash_verify_write_or_timeout(); // Wrong signature
void unk_86FBF58(); // Wrong signature
void unk_86FBFF4(); // Wrong signature
// 081DE820
void flash_bank_switch(u8 bank) {
*(u8*)0x0E005555 = 0xAA;
*(u8*)0x0E002AAA = 0x55;
*(u8*)0x0E005555 = 0xB0;
*(u8*)0x0E000000 = bank;
}
// 081DE844
u16 flash_get_manufacturer_and_device_type() {
// GBATEK#gbacartbackupflashrom
// > Also, reading anything (data or status/busy information) can be done <only> by opcodes
// > executed in WRAM (not from opcodes in ROM) (there's no such restriction for writing).
u16 buffer[0x22];
u8 (*flash_read_byte)(void*) = (u8(*)(void*))buffer;
flash_read_byte_to_buffer(buffer);
*(u8*)0x0E005555 = 0xAA; // enter chip identification mode
*(u8*)0x0E002AAA = 0x55;
*(u8*)0x0E005555 = 0x90;
{ volatile u16 cycles = 20000; while (cycles--); } // wait for chip
u8 device = flash_read_byte((void*)0xE000001);
u8 manufacturer = flash_read_byte((void*)0xE000000);
u16 chip_id = (device<<8) + manufacturer;
*(u8*)0x0E005555 = 0xAA; // exit chip identification mode
*(u8*)0x0E002AAA = 0x55;
*(u8*)0x0E005555 = 0xF0;
{ volatile u16 cycles = 20000; while (cycles--); } // wait for chip
return chip_id;
}
extern struct flash_chip_interface flash_chip_macronix_128k;
extern struct flash_chip_interface flash_chip_fallback;
extern struct flash_chip_interface flash_chip_sanyo_128k;
// 086FBF24
struct flash_chip_interface *flash_chip_list[] = {
&flash_chip_macronix_128k,
&flash_chip_sanyo_128k,
&flash_chip_fallback
};
// 086FBF70
struct flash_chip_interface flash_chip_macronix_128k = {
&sub_81DEFA4,
&flash_write_block,
&flash_erase_all,
&flash_erase_block,
&flash_verify_write_or_timeout,
&unk_86FBF58, {
0x20000,
0x1000,
0xC, 0,
0x20, 0,
3, 1,
0x09C2, 0 // chip id
}
};
// 086FBFA0
struct flash_chip_interface flash_chip_fallback = {
&sub_81DEFA4,
&flash_write_block,
&flash_erase_all,
&flash_erase_block,
&flash_verify_write_or_timeout,
&unk_86FBF58, {
0x20000,
0x1000,
0xC, 0,
0x20, 0,
3, 1,
0x0000, 0 // chip id
}
};
// 086FC00C
struct flash_chip_interface flash_chip_sanyo_128k = {
&sub_81DEFA4,
&flash_write_block,
&flash_erase_all,
&flash_erase_block,
&flash_verify_write_or_timeout,
&unk_86FBFF4, {
0x20000,
0x1000,
0xC, 0,
0x20, 0,
3, 1,
0x1362, 0 // chip id
}
};