ESP8266 ROM XTOS
来自Jack's Lab
(版本间的差异)
(以“== 逆向工程 == * http://dflund.se/~kongo/esp8266.bin/iram0.txt * http://esp8266-re.foogod.com/wiki/Boot_ROM <br><br>”为内容创建页面) |
(→CACHE_READ_ENABLE) |
||
| (未显示1个用户的6个中间版本) | |||
| 第3行: | 第3行: | ||
* http://dflund.se/~kongo/esp8266.bin/iram0.txt | * http://dflund.se/~kongo/esp8266.bin/iram0.txt | ||
* http://esp8266-re.foogod.com/wiki/Boot_ROM | * http://esp8266-re.foogod.com/wiki/Boot_ROM | ||
| + | |||
| + | <br><br> | ||
| + | |||
| + | == 探索 == | ||
| + | |||
| + | === SYSTEM_RTC_MEM_READ === | ||
| + | |||
| + | <source lang=cpp> | ||
| + | uint32 system_rtc_mem_read(int32 addr, void *buff, int32 length) | ||
| + | { | ||
| + | int32 blocks; | ||
| + | |||
| + | // validate reading a user block | ||
| + | //if (addr < 64) return 0; | ||
| + | if (buff == 0) return 0; | ||
| + | // validate 4 byte aligned | ||
| + | if (((uint32)buff & 0x3) != 0) return 0; | ||
| + | // validate length is multiple of 4 | ||
| + | if ((length & 0x3) != 0) return 0; | ||
| + | |||
| + | // check valid length from specified starting point | ||
| + | if (length > (0x300 - (addr * 4))) return 0; | ||
| + | |||
| + | // copy the data | ||
| + | for (blocks = (length >> 2) - 1; blocks >= 0; blocks--) { | ||
| + | volatile uint32 *ram = ((uint32*)buff) + blocks; | ||
| + | volatile uint32 *rtc = ((uint32*)0x60001100) + addr + blocks; | ||
| + | *ram = *rtc; | ||
| + | } | ||
| + | |||
| + | return 1; | ||
| + | } | ||
| + | </source> | ||
| + | |||
| + | <br><br> | ||
| + | |||
| + | === SYSTEM_RTC_MEM_WRITE === | ||
| + | |||
| + | <source lang=cpp> | ||
| + | uint32 system_rtc_mem_write(int32 addr, void *buff, int32 length) | ||
| + | { | ||
| + | int32 blocks; | ||
| + | |||
| + | // validate reading a user block | ||
| + | if (addr < 64) return 0; | ||
| + | if (buff == 0) return 0; | ||
| + | // validate 4 byte aligned | ||
| + | if (((uint32)buff & 0x3) != 0) return 0; | ||
| + | // validate length is multiple of 4 | ||
| + | if ((length & 0x3) != 0) return 0; | ||
| + | |||
| + | // check valid length from specified starting point | ||
| + | if (length > (0x300 - (addr * 4))) return 0; | ||
| + | |||
| + | // copy the data | ||
| + | for (blocks = (length >> 2) - 1; blocks >= 0; blocks--) { | ||
| + | volatile uint32 *ram = ((uint32*)buff) + blocks; | ||
| + | volatile uint32 *rtc = ((uint32*)0x60001100) + addr + blocks; | ||
| + | *rtc = *ram; | ||
| + | } | ||
| + | |||
| + | return 1; | ||
| + | } | ||
| + | </source> | ||
| + | |||
| + | <br><br> | ||
| + | |||
| + | === SYSTEM_GET_RST_INFO === | ||
| + | |||
| + | <source lang=cpp> | ||
| + | struct rst_info { | ||
| + | uint32 reason; | ||
| + | uint32 exccause; | ||
| + | uint32 epc1; | ||
| + | uint32 epc2; | ||
| + | uint32 epc3; | ||
| + | uint32 excvaddr; | ||
| + | uint32 depc; | ||
| + | }; | ||
| + | |||
| + | struct rst_info system_get_rst_info() | ||
| + | { | ||
| + | struct rst_info rst; | ||
| + | system_rtc_mem_read(0, &rst, sizeof(struct rst_info); | ||
| + | if (rst.reason >= 7) { | ||
| + | ets_memset(&rst, 0, sizeof(struct rst_info)); | ||
| + | } | ||
| + | if (rtc_get_reset_reason() == 2) { | ||
| + | ets_memset(&rst, 0, sizeof(struct rst_info)); | ||
| + | rst.reason = 6; | ||
| + | } | ||
| + | return rst; | ||
| + | } | ||
| + | </source> | ||
| + | |||
| + | <br> | ||
| + | |||
| + | <br><br> | ||
| + | |||
| + | == CACHE_READ_ENABLE == | ||
| + | |||
| + | Cache_Read_Enable is defined in the Boot ROM (XTOS) at memory address 0x40004678 | ||
| + | |||
| + | |||
| + | void Cache_Read_Enable(uint8 odd_even, uint8 mb_count, unt8 no_idea); | ||
| + | |||
| + | |||
| + | Valid values for odd_even: | ||
| + | |||
| + | 0 – clears bits 24 & 25 of control register 0x3FF0000C | ||
| + | 1 – clears bit 24, sets bit 25 | ||
| + | other – clears bit 25, sets bit 24 | ||
| + | |||
| + | |||
| + | Function of odd_even: | ||
| + | |||
| + | 0 – allows access to even numbered mb | ||
| + | 1 – allow access to odd numbered mb | ||
| + | other – appears to do the same as 1, there must be a difference but I haven’t worked out what it it | ||
| + | |||
| + | |||
| + | Valid values for mb_count: | ||
| + | |||
| + | 0-7 – set bits 16, 17 & 18 of control register 0x3FF0000C | ||
| + | |||
| + | Function of mb_count: | ||
| + | |||
| + | Which odd or even bank to map (according to odd_even option) | ||
| + | |||
| + | e.g. mb_count = 0, odd_even = 0 -> map first 8Mbit of flash | ||
| + | e.g. mb_count = 0, odd_even = 1 -> map second 8Mbit of flash | ||
| + | e.g. mb_count = 1, odd_even = 0 -> map third 8Mbit of flash | ||
| + | e.g. mb_count = 1, odd_even = 1 -> map fourth 8Mbit of flash | ||
| + | |||
| + | |||
| + | Valid values for no_idea: | ||
| + | |||
| + | 0 – sets bit 3 of 0x3FF00024 | ||
| + | 1 – sets bit 26 of 0x3FF0000C and sets bits 3 & 4 of 0x3FF00024 | ||
| + | |||
| + | Function of no_idea: | ||
| + | |||
| + | The clue is in the name, I can’t work out what this does from my experiments, but the SDK always sets this to 1. | ||
| + | |||
| + | <source lang=cpp> | ||
| + | void Cache_Read_Enable(uint8 odd_even, uint8 mb_count, uint8 no_idea) { | ||
| + | |||
| + | uint32 base1 = 0x3FEFFE00; | ||
| + | volatile uint32 *r20c = (uint32*)(base1 + 0x20c); | ||
| + | volatile uint32 *r224 = (uint32*)(base1 + 0x224); | ||
| + | |||
| + | uint32 base2 = 0x60000200; | ||
| + | volatile uint32 *r008 = (uint32*)(base2 + 8); | ||
| + | |||
| + | while (*r20c & 0x100) { | ||
| + | *r20c &= 0xeff; | ||
| + | } | ||
| + | |||
| + | *r008 &= 0xFFFDFFFF; | ||
| + | *r20c &= 0x7e; | ||
| + | *r20c |= 0x1; | ||
| + | |||
| + | while ((*r20c & 0x2) == 0) { | ||
| + | } | ||
| + | |||
| + | *r20c &= 0x7e; | ||
| + | *r008 |= 0x20000; | ||
| + | |||
| + | if (odd_even == 0) { | ||
| + | *r20c &= 0xFCFFFFFF; // clear bits 24 & 25 | ||
| + | } else if (odd_even == 1) { | ||
| + | *r20c &= 0xFEFFFFFF; // clear bit 24 | ||
| + | *r20c |= 0x2000000; // set bit 25 | ||
| + | } else { | ||
| + | *r20c &= 0xFDFFFFFF; // clear bit 25 | ||
| + | *r20c |= 0x1000000; // set bit 24 | ||
| + | } | ||
| + | |||
| + | *r20c &= 0xFBF8FFFF; // clear bits 16, 17, 18, 26 | ||
| + | *r20c |= ((no_idea << 0x1a) | (mb_count << 0x10)); // set bits 26 & 18/17/16 | ||
| + | // no_idea should be 0-1 (1 bit), mb_count 0-7 (3 bits) | ||
| + | |||
| + | if (no_idea == 0) { | ||
| + | *r224 |= 0x08; // set bit 3 | ||
| + | } else { | ||
| + | *r224 |= 0x18; // set bits 3 & 4 | ||
| + | } | ||
| + | |||
| + | while ((*r20c & 0x100) == 0) { | ||
| + | *r20c |= 0x100; | ||
| + | } | ||
| + | |||
| + | return; | ||
| + | } | ||
| + | </source> | ||
<br><br> | <br><br> | ||
2015年12月11日 (五) 08:01的最后版本
目录 |
[编辑] 1 逆向工程
[编辑] 2 探索
[编辑] 2.1 SYSTEM_RTC_MEM_READ
uint32 system_rtc_mem_read(int32 addr, void *buff, int32 length)
{
int32 blocks;
// validate reading a user block
//if (addr < 64) return 0;
if (buff == 0) return 0;
// validate 4 byte aligned
if (((uint32)buff & 0x3) != 0) return 0;
// validate length is multiple of 4
if ((length & 0x3) != 0) return 0;
// check valid length from specified starting point
if (length > (0x300 - (addr * 4))) return 0;
// copy the data
for (blocks = (length >> 2) - 1; blocks >= 0; blocks--) {
volatile uint32 *ram = ((uint32*)buff) + blocks;
volatile uint32 *rtc = ((uint32*)0x60001100) + addr + blocks;
*ram = *rtc;
}
return 1;
}
[编辑] 2.2 SYSTEM_RTC_MEM_WRITE
uint32 system_rtc_mem_write(int32 addr, void *buff, int32 length)
{
int32 blocks;
// validate reading a user block
if (addr < 64) return 0;
if (buff == 0) return 0;
// validate 4 byte aligned
if (((uint32)buff & 0x3) != 0) return 0;
// validate length is multiple of 4
if ((length & 0x3) != 0) return 0;
// check valid length from specified starting point
if (length > (0x300 - (addr * 4))) return 0;
// copy the data
for (blocks = (length >> 2) - 1; blocks >= 0; blocks--) {
volatile uint32 *ram = ((uint32*)buff) + blocks;
volatile uint32 *rtc = ((uint32*)0x60001100) + addr + blocks;
*rtc = *ram;
}
return 1;
}
[编辑] 2.3 SYSTEM_GET_RST_INFO
struct rst_info {
uint32 reason;
uint32 exccause;
uint32 epc1;
uint32 epc2;
uint32 epc3;
uint32 excvaddr;
uint32 depc;
};
struct rst_info system_get_rst_info()
{
struct rst_info rst;
system_rtc_mem_read(0, &rst, sizeof(struct rst_info);
if (rst.reason >= 7) {
ets_memset(&rst, 0, sizeof(struct rst_info));
}
if (rtc_get_reset_reason() == 2) {
ets_memset(&rst, 0, sizeof(struct rst_info));
rst.reason = 6;
}
return rst;
}
[编辑] 3 CACHE_READ_ENABLE
Cache_Read_Enable is defined in the Boot ROM (XTOS) at memory address 0x40004678
void Cache_Read_Enable(uint8 odd_even, uint8 mb_count, unt8 no_idea);
Valid values for odd_even:
0 – clears bits 24 & 25 of control register 0x3FF0000C 1 – clears bit 24, sets bit 25 other – clears bit 25, sets bit 24
Function of odd_even:
0 – allows access to even numbered mb 1 – allow access to odd numbered mb other – appears to do the same as 1, there must be a difference but I haven’t worked out what it it
Valid values for mb_count:
0-7 – set bits 16, 17 & 18 of control register 0x3FF0000C
Function of mb_count:
Which odd or even bank to map (according to odd_even option)
e.g. mb_count = 0, odd_even = 0 -> map first 8Mbit of flash e.g. mb_count = 0, odd_even = 1 -> map second 8Mbit of flash e.g. mb_count = 1, odd_even = 0 -> map third 8Mbit of flash e.g. mb_count = 1, odd_even = 1 -> map fourth 8Mbit of flash
Valid values for no_idea:
0 – sets bit 3 of 0x3FF00024 1 – sets bit 26 of 0x3FF0000C and sets bits 3 & 4 of 0x3FF00024
Function of no_idea:
The clue is in the name, I can’t work out what this does from my experiments, but the SDK always sets this to 1.
void Cache_Read_Enable(uint8 odd_even, uint8 mb_count, uint8 no_idea) {
uint32 base1 = 0x3FEFFE00;
volatile uint32 *r20c = (uint32*)(base1 + 0x20c);
volatile uint32 *r224 = (uint32*)(base1 + 0x224);
uint32 base2 = 0x60000200;
volatile uint32 *r008 = (uint32*)(base2 + 8);
while (*r20c & 0x100) {
*r20c &= 0xeff;
}
*r008 &= 0xFFFDFFFF;
*r20c &= 0x7e;
*r20c |= 0x1;
while ((*r20c & 0x2) == 0) {
}
*r20c &= 0x7e;
*r008 |= 0x20000;
if (odd_even == 0) {
*r20c &= 0xFCFFFFFF; // clear bits 24 & 25
} else if (odd_even == 1) {
*r20c &= 0xFEFFFFFF; // clear bit 24
*r20c |= 0x2000000; // set bit 25
} else {
*r20c &= 0xFDFFFFFF; // clear bit 25
*r20c |= 0x1000000; // set bit 24
}
*r20c &= 0xFBF8FFFF; // clear bits 16, 17, 18, 26
*r20c |= ((no_idea << 0x1a) | (mb_count << 0x10)); // set bits 26 & 18/17/16
// no_idea should be 0-1 (1 bit), mb_count 0-7 (3 bits)
if (no_idea == 0) {
*r224 |= 0x08; // set bit 3
} else {
*r224 |= 0x18; // set bits 3 & 4
}
while ((*r20c & 0x100) == 0) {
*r20c |= 0x100;
}
return;
}