mirror of
https://github.com/wiiu-env/wiiu-nanddumper-payload.git
synced 2024-11-22 03:19:17 +01:00
Dump OTP and SEEPROM
This commit is contained in:
parent
dad9a3fbbd
commit
1d7fb42aa3
@ -59,6 +59,7 @@ $(PROJECTNAME)_syms.h:
|
||||
@echo "#define $(PROJECTNAME)_SYMS_H" >> $@
|
||||
@$(OBJDUMP) -EB -t -marm $(PROJECTNAME).elf | grep 'g F .text' | grep -v '.hidden' | awk '{print "#define " $$6 " 0x" $$1}' >> $@
|
||||
@$(OBJDUMP) -EB -t -marm $(PROJECTNAME).elf | grep -e 'g .text' -e '_bss_' | awk '{print "#define " $$5 " 0x" $$1}' >> $@
|
||||
@$(OBJDUMP) -EB -t -marm $(PROJECTNAME).elf | grep -e 'g O .dumper_config' | awk '{print "#define " $$6 " 0x" $$1}' >> $@
|
||||
@echo "#endif" >> $@
|
||||
|
||||
clean:
|
||||
|
@ -8,6 +8,9 @@ SECTIONS
|
||||
*(.rodata*);
|
||||
}
|
||||
_text_end = .;
|
||||
.dumper_config : {
|
||||
*(.dumper_config*);
|
||||
}
|
||||
|
||||
.bss (0x10835000 + 0x1406554) : {
|
||||
_bss_start = .;
|
||||
|
@ -8,6 +8,9 @@
|
||||
#include "text.h"
|
||||
#include "hardware_registers.h"
|
||||
#include "svc.h"
|
||||
#include "fs_config.h"
|
||||
|
||||
fs_config dumper_config __attribute__((section(".dumper_config")));
|
||||
|
||||
#define IO_BUFFER_SIZE 0x40000
|
||||
#define IO_BUFFER_SPARE_SIZE (IO_BUFFER_SIZE+0x2000)
|
||||
@ -233,15 +236,10 @@ void dump_nand_complete()
|
||||
_printf(20, offset_y, "Init SD card.... Success!");
|
||||
offset_y += 10;
|
||||
|
||||
int * dumpSlc = (int *)(0x107f8200 - 4);
|
||||
int * dumpSlccmpt = (int *)(0x107f8200 - 8);
|
||||
int * dumpMlc = (int *)(0x107f8200 - 12);
|
||||
|
||||
|
||||
//wait_format_confirmation();
|
||||
|
||||
u32 mlc_sector_count = 0;
|
||||
if (*dumpMlc) {
|
||||
if (dumper_config.dump_mlc) {
|
||||
mlc_init();
|
||||
FS_SLEEP(1000);
|
||||
|
||||
@ -268,17 +266,53 @@ void dump_nand_complete()
|
||||
svcShutdown(SHUTDOWN_TYPE_REBOOT);
|
||||
}*/
|
||||
|
||||
if (*dumpSlc) {
|
||||
if (dumper_config.dump_otp) {
|
||||
_printf(20, offset_y, "Writing otp...");
|
||||
FL_FILE *file = fl_fopen("/otp.bin", "w");
|
||||
if (!file) {
|
||||
_printf(20, offset_y+10, "Failed to open /otp.bin for writing!");
|
||||
goto error;
|
||||
}
|
||||
// It doesn't work if we try write directly this buffer, does it try to access too much?
|
||||
memcpy(io_buffer, dumper_config.otp_buffer, sizeof(dumper_config.otp_buffer));
|
||||
if (fl_fwrite(io_buffer, 1, sizeof(dumper_config.otp_buffer), file) != sizeof(dumper_config.otp_buffer)) {
|
||||
fl_fclose(file);
|
||||
_printf(20, offset_y+10, "Failed to write otp to file!");
|
||||
goto error;
|
||||
}
|
||||
fl_fclose(file);
|
||||
_printf(20, offset_y, "Writing otp... Success!");
|
||||
offset_y += 10;
|
||||
}
|
||||
if (dumper_config.dump_seeprom) {
|
||||
_printf(20, offset_y, "Writing seeprom...");
|
||||
FL_FILE *file = fl_fopen("/seeprom.bin", "w");
|
||||
if (!file) {
|
||||
_printf(20, offset_y+10, "Failed to open /seeprom.bin for writing!");
|
||||
goto error;
|
||||
}
|
||||
// It doesn't work if we try write directly this buffer, does it try to access too much?
|
||||
memcpy(io_buffer, dumper_config.seeprom_buffer, sizeof(dumper_config.seeprom_buffer));
|
||||
if (fl_fwrite(io_buffer, 1, sizeof(dumper_config.seeprom_buffer), file) != sizeof(dumper_config.seeprom_buffer)) {
|
||||
fl_fclose(file);
|
||||
_printf(20, offset_y+10, "Failed to write seeprom to file!");
|
||||
goto error;
|
||||
}
|
||||
fl_fclose(file);
|
||||
_printf(20, offset_y, "Writing seeprom... Success!");
|
||||
offset_y += 10;
|
||||
}
|
||||
if (dumper_config.dump_slc) {
|
||||
if (slc_dump(FS_SLC_PHYS_DEV_STRUCT, "slc ", "/slc.bin", offset_y))
|
||||
goto error;
|
||||
offset_y += 10;
|
||||
}
|
||||
if (*dumpSlccmpt) {
|
||||
if (dumper_config.dump_slccmpt) {
|
||||
if (slc_dump(FS_SLCCMPT_PHYS_DEV_STRUCT, "slccmpt", "/slccmpt.bin", offset_y))
|
||||
goto error;
|
||||
offset_y += 10;
|
||||
}
|
||||
if (*dumpMlc) {
|
||||
if (dumper_config.dump_mlc) {
|
||||
if (mlc_dump(mlc_sector_count, offset_y))
|
||||
goto error;
|
||||
offset_y += 10;
|
||||
|
14
ios_fs/source/fs_config.h
Normal file
14
ios_fs/source/fs_config.h
Normal file
@ -0,0 +1,14 @@
|
||||
#ifndef _FS_CONFIG_H
|
||||
#define _FS_CONFIG_H
|
||||
|
||||
typedef struct {
|
||||
int dump_slc;
|
||||
int dump_slccmpt;
|
||||
int dump_mlc;
|
||||
int dump_otp;
|
||||
int dump_seeprom;
|
||||
char otp_buffer[0x400];
|
||||
char seeprom_buffer[0x200];
|
||||
} fs_config;
|
||||
|
||||
#endif
|
@ -25,7 +25,9 @@
|
||||
#include "elf_patcher.h"
|
||||
#include "ios_fs_patches.h"
|
||||
#include "config.h"
|
||||
#include "utils.h"
|
||||
#include "../../ios_fs/ios_fs_syms.h"
|
||||
#include "../../ios_fs/source/fs_config.h"
|
||||
|
||||
#define FS_PHYS_DIFF 0
|
||||
|
||||
@ -51,6 +53,9 @@
|
||||
extern const patch_table_t fs_patches_table[];
|
||||
extern const patch_table_t fs_patches_table_end[];
|
||||
|
||||
extern unsigned char otp_buffer[0x400];
|
||||
extern unsigned char seeprom_buffer[0x400];
|
||||
|
||||
u32 fs_get_phys_code_base(void)
|
||||
{
|
||||
return _text_start + FS_PHYS_DIFF;
|
||||
@ -58,6 +63,8 @@ u32 fs_get_phys_code_base(void)
|
||||
|
||||
void fs_run_patches(u32 ios_elf_start)
|
||||
{
|
||||
fs_config config;
|
||||
|
||||
// write wupserver code and bss
|
||||
section_write(ios_elf_start, _text_start, (void*)fs_get_phys_code_base(), _text_end - _text_start);
|
||||
section_write_bss(ios_elf_start, _bss_start, _bss_end - _bss_start);
|
||||
@ -78,9 +85,16 @@ void fs_run_patches(u32 ios_elf_start)
|
||||
|
||||
section_write_word(ios_elf_start, FS_SLC_ECC_CHECK, ARM_B(FS_SLC_ECC_CHECK, eccCheck_patch));
|
||||
|
||||
section_write_word(ios_elf_start, (_text_start - 4), cfw_config.dumpSlc);
|
||||
section_write_word(ios_elf_start, (_text_start - 8), cfw_config.dumpSlccmpt);
|
||||
section_write_word(ios_elf_start, (_text_start - 12), cfw_config.dumpMlc);
|
||||
config.dump_slc = cfw_config.dumpSlc;
|
||||
config.dump_slccmpt = cfw_config.dumpSlccmpt;
|
||||
config.dump_mlc = cfw_config.dumpMlc;
|
||||
config.dump_otp = cfw_config.dumpOtp;
|
||||
config.dump_seeprom = cfw_config.dumpSeeprom;
|
||||
if (cfw_config.dumpOtp)
|
||||
kernel_memcpy(config.otp_buffer, otp_buffer, sizeof(config.otp_buffer));
|
||||
if (cfw_config.dumpSeeprom)
|
||||
kernel_memcpy(config.seeprom_buffer, seeprom_buffer, sizeof(config.seeprom_buffer));
|
||||
section_write(ios_elf_start, dumper_config, &config, sizeof(config));
|
||||
|
||||
//section_write_word(ios_elf_start, FS_USB_READ, ARM_B(FS_USB_READ, usbRead_patch));
|
||||
//section_write_word(ios_elf_start, FS_USB_WRITE, ARM_B(FS_USB_WRITE, usbWrite_patch));
|
||||
|
@ -38,7 +38,7 @@ extern void __KERNEL_CODE_END(void);
|
||||
extern const patch_table_t kernel_patches_table[];
|
||||
extern const patch_table_t kernel_patches_table_end[];
|
||||
|
||||
static u8 otp_buffer[0x400];
|
||||
//static u8 otp_buffer[0x400];
|
||||
|
||||
static const u32 mcpIoMappings_patch[] =
|
||||
{
|
||||
@ -60,7 +60,7 @@ static u32 kernel_syscall_0x81(u32 address)
|
||||
return *(volatile u32*)address;
|
||||
}
|
||||
|
||||
static int kernel_read_otp_internal(int index, void* out_buf, u32 size)
|
||||
/*static int kernel_read_otp_internal(int index, void* out_buf, u32 size)
|
||||
{
|
||||
kernel_memcpy(out_buf, otp_buffer + (index << 2), size);
|
||||
return 0;
|
||||
@ -85,7 +85,7 @@ int kernel_init_otp_buffer(u32 sd_sector, int dumpFound)
|
||||
FSA_SDWriteRawSectors(otp_buffer, sd_sector, 2);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
}*/
|
||||
|
||||
void kernel_launch_ios(u32 launch_address, u32 L, u32 C, u32 H)
|
||||
{
|
||||
|
@ -34,6 +34,9 @@
|
||||
|
||||
cfw_config_t cfw_config;
|
||||
|
||||
unsigned char otp_buffer[0x400];
|
||||
unsigned char seeprom_buffer[0x400];
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u32 size;
|
||||
@ -64,16 +67,105 @@ static const char repairData_usb_root_thread[] = {
|
||||
0xE5,0x9F,0x0E,0x68,0xEB,0x00,0xB3,0x20,
|
||||
};
|
||||
|
||||
// based on mini implementation by sven peter
|
||||
#define LT_TIMER 0x0d800010
|
||||
#define LT_GPIO_OUT 0x0d8000e0
|
||||
#define LT_GPIO_IN 0x0d8000e8
|
||||
|
||||
#define EEPROM_SPI_CS 0x400
|
||||
#define EEPROM_SPI_SCK 0x800
|
||||
#define EEPROM_SPI_MOSI 0x1000
|
||||
#define EEPROM_SPI_MISO 0x2000
|
||||
|
||||
#define HW_REG(reg) (*(volatile unsigned int*)(reg))
|
||||
|
||||
static inline void _delay(u32 ticks)
|
||||
{
|
||||
u32 now = HW_REG(LT_TIMER);
|
||||
while((HW_REG(LT_TIMER) - now) < ticks);
|
||||
}
|
||||
|
||||
static u32 spi_read(int bit_count)
|
||||
{
|
||||
u32 word = 0;
|
||||
while(bit_count--)
|
||||
{
|
||||
word <<= 1;
|
||||
|
||||
HW_REG(LT_GPIO_OUT) |= EEPROM_SPI_SCK;
|
||||
_delay(9);
|
||||
|
||||
HW_REG(LT_GPIO_OUT) &= ~EEPROM_SPI_SCK;
|
||||
_delay(9);
|
||||
|
||||
word |= ((HW_REG(LT_GPIO_IN) & EEPROM_SPI_MISO) != 0);
|
||||
}
|
||||
return word;
|
||||
}
|
||||
|
||||
static void spi_write(u32 word, int bit_count)
|
||||
{
|
||||
while(bit_count--)
|
||||
{
|
||||
if(word & (1 << bit_count))
|
||||
{
|
||||
HW_REG(LT_GPIO_OUT) |= EEPROM_SPI_MOSI;
|
||||
}
|
||||
else
|
||||
{
|
||||
HW_REG(LT_GPIO_OUT) &= ~EEPROM_SPI_MOSI;
|
||||
}
|
||||
_delay(9);
|
||||
|
||||
HW_REG(LT_GPIO_OUT) |= EEPROM_SPI_SCK;
|
||||
_delay(9);
|
||||
|
||||
HW_REG(LT_GPIO_OUT) &= ~EEPROM_SPI_SCK;
|
||||
_delay(9);
|
||||
}
|
||||
}
|
||||
|
||||
static int seeprom_read(u16 *dst, int offset, int size)
|
||||
{
|
||||
int i;
|
||||
offset >>= 1;
|
||||
size >>= 1;
|
||||
|
||||
HW_REG(LT_GPIO_OUT) &= ~EEPROM_SPI_SCK;
|
||||
HW_REG(LT_GPIO_OUT) &= ~EEPROM_SPI_CS;
|
||||
_delay(9);
|
||||
|
||||
for(i = 0; i < size; ++i, ++offset)
|
||||
{
|
||||
HW_REG(LT_GPIO_OUT) |= EEPROM_SPI_CS;
|
||||
spi_write((0x600 | offset), 11);
|
||||
|
||||
dst[i] = spi_read(16);
|
||||
|
||||
HW_REG(LT_GPIO_OUT) &= ~EEPROM_SPI_CS;
|
||||
_delay(9);
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
int _main()
|
||||
{
|
||||
void(*invalidate_icache)() = (void(*)())0x0812DCF0;
|
||||
void(*invalidate_dcache)(unsigned int, unsigned int) = (void(*)())0x08120164;
|
||||
void(*flush_dcache)(unsigned int, unsigned int) = (void(*)())0x08120160;
|
||||
int (*orig_kernel_read_otp_internal)(int index, void* out_buf, u32 size) = (void*)0x08120248;
|
||||
|
||||
flush_dcache(0x081200F0, 0x4001); // giving a size >= 0x4000 flushes all cache
|
||||
// We don't have the config yet, so read it anyway
|
||||
orig_kernel_read_otp_internal(0, otp_buffer, 0x400);
|
||||
|
||||
flush_dcache(0x081200F0, 0x4001); // giving a size >= 0x4000 flushes all cache
|
||||
|
||||
int level = disable_interrupts();
|
||||
|
||||
// We don't have the config yet, so read it anyway
|
||||
seeprom_read(seeprom_buffer, 0, 0x200);
|
||||
|
||||
unsigned int control_register = disable_mmu();
|
||||
|
||||
/* Save the request handle so we can reply later */
|
||||
|
@ -88,6 +88,8 @@ void default_config(cfw_config_t * config)
|
||||
config->dumpSlc = 1;
|
||||
config->dumpSlccmpt = 1;
|
||||
config->dumpMlc = 0;
|
||||
config->dumpOtp = 1;
|
||||
config->dumpSeeprom = 1;
|
||||
}
|
||||
|
||||
/*int read_config(cfw_config_t * config)
|
||||
|
@ -42,6 +42,8 @@ typedef struct
|
||||
int dumpSlc;
|
||||
int dumpSlccmpt;
|
||||
int dumpMlc;
|
||||
int dumpOtp;
|
||||
int dumpSeeprom;
|
||||
} cfw_config_t;
|
||||
|
||||
void default_config(cfw_config_t * config);
|
||||
|
@ -36,7 +36,7 @@
|
||||
#include "dynamic_libs/socket_functions.h"
|
||||
#include "cfw_config.h"
|
||||
|
||||
#define MAX_CONFIG_SETTINGS 3
|
||||
#define MAX_CONFIG_SETTINGS 5
|
||||
//#define MAX_CONFIG_SETTINGS_EXPERT 9
|
||||
//#define MAX_CONFIG_SETTINGS_DEFAULT (MAX_CONFIG_SETTINGS_EXPERT - 3)
|
||||
|
||||
@ -163,6 +163,12 @@ int ShowMenu(cfw_config_t * currentConfig)
|
||||
case 2:
|
||||
config.dumpMlc = !config.dumpMlc;
|
||||
break;
|
||||
case 3:
|
||||
config.dumpOtp = !config.dumpOtp;
|
||||
break;
|
||||
case 4:
|
||||
config.dumpSeeprom = !config.dumpSeeprom;
|
||||
break;
|
||||
/*case 0:
|
||||
config.viewMode = !config.viewMode;
|
||||
max_config_item = config.viewMode ? MAX_CONFIG_SETTINGS_EXPERT : MAX_CONFIG_SETTINGS_DEFAULT;
|
||||
|
Loading…
Reference in New Issue
Block a user