mirror of
https://github.com/wiiu-env/wiiu-nanddumper-payload.git
synced 2024-11-22 11:29:16 +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" >> $@
|
@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 '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 .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" >> $@
|
@echo "#endif" >> $@
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
|
@ -8,6 +8,9 @@ SECTIONS
|
|||||||
*(.rodata*);
|
*(.rodata*);
|
||||||
}
|
}
|
||||||
_text_end = .;
|
_text_end = .;
|
||||||
|
.dumper_config : {
|
||||||
|
*(.dumper_config*);
|
||||||
|
}
|
||||||
|
|
||||||
.bss (0x10835000 + 0x1406554) : {
|
.bss (0x10835000 + 0x1406554) : {
|
||||||
_bss_start = .;
|
_bss_start = .;
|
||||||
|
@ -8,6 +8,9 @@
|
|||||||
#include "text.h"
|
#include "text.h"
|
||||||
#include "hardware_registers.h"
|
#include "hardware_registers.h"
|
||||||
#include "svc.h"
|
#include "svc.h"
|
||||||
|
#include "fs_config.h"
|
||||||
|
|
||||||
|
fs_config dumper_config __attribute__((section(".dumper_config")));
|
||||||
|
|
||||||
#define IO_BUFFER_SIZE 0x40000
|
#define IO_BUFFER_SIZE 0x40000
|
||||||
#define IO_BUFFER_SPARE_SIZE (IO_BUFFER_SIZE+0x2000)
|
#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!");
|
_printf(20, offset_y, "Init SD card.... Success!");
|
||||||
offset_y += 10;
|
offset_y += 10;
|
||||||
|
|
||||||
int * dumpSlc = (int *)(0x107f8200 - 4);
|
|
||||||
int * dumpSlccmpt = (int *)(0x107f8200 - 8);
|
|
||||||
int * dumpMlc = (int *)(0x107f8200 - 12);
|
|
||||||
|
|
||||||
|
|
||||||
//wait_format_confirmation();
|
//wait_format_confirmation();
|
||||||
|
|
||||||
u32 mlc_sector_count = 0;
|
u32 mlc_sector_count = 0;
|
||||||
if (*dumpMlc) {
|
if (dumper_config.dump_mlc) {
|
||||||
mlc_init();
|
mlc_init();
|
||||||
FS_SLEEP(1000);
|
FS_SLEEP(1000);
|
||||||
|
|
||||||
@ -268,17 +266,53 @@ void dump_nand_complete()
|
|||||||
svcShutdown(SHUTDOWN_TYPE_REBOOT);
|
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))
|
if (slc_dump(FS_SLC_PHYS_DEV_STRUCT, "slc ", "/slc.bin", offset_y))
|
||||||
goto error;
|
goto error;
|
||||||
offset_y += 10;
|
offset_y += 10;
|
||||||
}
|
}
|
||||||
if (*dumpSlccmpt) {
|
if (dumper_config.dump_slccmpt) {
|
||||||
if (slc_dump(FS_SLCCMPT_PHYS_DEV_STRUCT, "slccmpt", "/slccmpt.bin", offset_y))
|
if (slc_dump(FS_SLCCMPT_PHYS_DEV_STRUCT, "slccmpt", "/slccmpt.bin", offset_y))
|
||||||
goto error;
|
goto error;
|
||||||
offset_y += 10;
|
offset_y += 10;
|
||||||
}
|
}
|
||||||
if (*dumpMlc) {
|
if (dumper_config.dump_mlc) {
|
||||||
if (mlc_dump(mlc_sector_count, offset_y))
|
if (mlc_dump(mlc_sector_count, offset_y))
|
||||||
goto error;
|
goto error;
|
||||||
offset_y += 10;
|
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 "elf_patcher.h"
|
||||||
#include "ios_fs_patches.h"
|
#include "ios_fs_patches.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
#include "utils.h"
|
||||||
#include "../../ios_fs/ios_fs_syms.h"
|
#include "../../ios_fs/ios_fs_syms.h"
|
||||||
|
#include "../../ios_fs/source/fs_config.h"
|
||||||
|
|
||||||
#define FS_PHYS_DIFF 0
|
#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[];
|
||||||
extern const patch_table_t fs_patches_table_end[];
|
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)
|
u32 fs_get_phys_code_base(void)
|
||||||
{
|
{
|
||||||
return _text_start + FS_PHYS_DIFF;
|
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)
|
void fs_run_patches(u32 ios_elf_start)
|
||||||
{
|
{
|
||||||
|
fs_config config;
|
||||||
|
|
||||||
// write wupserver code and bss
|
// write wupserver code and bss
|
||||||
section_write(ios_elf_start, _text_start, (void*)fs_get_phys_code_base(), _text_end - _text_start);
|
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);
|
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, FS_SLC_ECC_CHECK, ARM_B(FS_SLC_ECC_CHECK, eccCheck_patch));
|
||||||
|
|
||||||
section_write_word(ios_elf_start, (_text_start - 4), cfw_config.dumpSlc);
|
config.dump_slc = cfw_config.dumpSlc;
|
||||||
section_write_word(ios_elf_start, (_text_start - 8), cfw_config.dumpSlccmpt);
|
config.dump_slccmpt = cfw_config.dumpSlccmpt;
|
||||||
section_write_word(ios_elf_start, (_text_start - 12), cfw_config.dumpMlc);
|
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_READ, ARM_B(FS_USB_READ, usbRead_patch));
|
||||||
//section_write_word(ios_elf_start, FS_USB_WRITE, ARM_B(FS_USB_WRITE, usbWrite_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[];
|
||||||
extern const patch_table_t kernel_patches_table_end[];
|
extern const patch_table_t kernel_patches_table_end[];
|
||||||
|
|
||||||
static u8 otp_buffer[0x400];
|
//static u8 otp_buffer[0x400];
|
||||||
|
|
||||||
static const u32 mcpIoMappings_patch[] =
|
static const u32 mcpIoMappings_patch[] =
|
||||||
{
|
{
|
||||||
@ -60,7 +60,7 @@ static u32 kernel_syscall_0x81(u32 address)
|
|||||||
return *(volatile 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);
|
kernel_memcpy(out_buf, otp_buffer + (index << 2), size);
|
||||||
return 0;
|
return 0;
|
||||||
@ -85,7 +85,7 @@ int kernel_init_otp_buffer(u32 sd_sector, int dumpFound)
|
|||||||
FSA_SDWriteRawSectors(otp_buffer, sd_sector, 2);
|
FSA_SDWriteRawSectors(otp_buffer, sd_sector, 2);
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}*/
|
||||||
|
|
||||||
void kernel_launch_ios(u32 launch_address, u32 L, u32 C, u32 H)
|
void kernel_launch_ios(u32 launch_address, u32 L, u32 C, u32 H)
|
||||||
{
|
{
|
||||||
|
@ -34,6 +34,9 @@
|
|||||||
|
|
||||||
cfw_config_t cfw_config;
|
cfw_config_t cfw_config;
|
||||||
|
|
||||||
|
unsigned char otp_buffer[0x400];
|
||||||
|
unsigned char seeprom_buffer[0x400];
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
u32 size;
|
u32 size;
|
||||||
@ -64,16 +67,105 @@ static const char repairData_usb_root_thread[] = {
|
|||||||
0xE5,0x9F,0x0E,0x68,0xEB,0x00,0xB3,0x20,
|
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()
|
int _main()
|
||||||
{
|
{
|
||||||
void(*invalidate_icache)() = (void(*)())0x0812DCF0;
|
void(*invalidate_icache)() = (void(*)())0x0812DCF0;
|
||||||
void(*invalidate_dcache)(unsigned int, unsigned int) = (void(*)())0x08120164;
|
void(*invalidate_dcache)(unsigned int, unsigned int) = (void(*)())0x08120164;
|
||||||
void(*flush_dcache)(unsigned int, unsigned int) = (void(*)())0x08120160;
|
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();
|
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();
|
unsigned int control_register = disable_mmu();
|
||||||
|
|
||||||
/* Save the request handle so we can reply later */
|
/* Save the request handle so we can reply later */
|
||||||
|
@ -88,6 +88,8 @@ void default_config(cfw_config_t * config)
|
|||||||
config->dumpSlc = 1;
|
config->dumpSlc = 1;
|
||||||
config->dumpSlccmpt = 1;
|
config->dumpSlccmpt = 1;
|
||||||
config->dumpMlc = 0;
|
config->dumpMlc = 0;
|
||||||
|
config->dumpOtp = 1;
|
||||||
|
config->dumpSeeprom = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*int read_config(cfw_config_t * config)
|
/*int read_config(cfw_config_t * config)
|
||||||
|
@ -42,6 +42,8 @@ typedef struct
|
|||||||
int dumpSlc;
|
int dumpSlc;
|
||||||
int dumpSlccmpt;
|
int dumpSlccmpt;
|
||||||
int dumpMlc;
|
int dumpMlc;
|
||||||
|
int dumpOtp;
|
||||||
|
int dumpSeeprom;
|
||||||
} cfw_config_t;
|
} cfw_config_t;
|
||||||
|
|
||||||
void default_config(cfw_config_t * config);
|
void default_config(cfw_config_t * config);
|
||||||
|
@ -36,7 +36,7 @@
|
|||||||
#include "dynamic_libs/socket_functions.h"
|
#include "dynamic_libs/socket_functions.h"
|
||||||
#include "cfw_config.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_EXPERT 9
|
||||||
//#define MAX_CONFIG_SETTINGS_DEFAULT (MAX_CONFIG_SETTINGS_EXPERT - 3)
|
//#define MAX_CONFIG_SETTINGS_DEFAULT (MAX_CONFIG_SETTINGS_EXPERT - 3)
|
||||||
|
|
||||||
@ -163,6 +163,12 @@ int ShowMenu(cfw_config_t * currentConfig)
|
|||||||
case 2:
|
case 2:
|
||||||
config.dumpMlc = !config.dumpMlc;
|
config.dumpMlc = !config.dumpMlc;
|
||||||
break;
|
break;
|
||||||
|
case 3:
|
||||||
|
config.dumpOtp = !config.dumpOtp;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
config.dumpSeeprom = !config.dumpSeeprom;
|
||||||
|
break;
|
||||||
/*case 0:
|
/*case 0:
|
||||||
config.viewMode = !config.viewMode;
|
config.viewMode = !config.viewMode;
|
||||||
max_config_item = config.viewMode ? MAX_CONFIG_SETTINGS_EXPERT : MAX_CONFIG_SETTINGS_DEFAULT;
|
max_config_item = config.viewMode ? MAX_CONFIG_SETTINGS_EXPERT : MAX_CONFIG_SETTINGS_DEFAULT;
|
||||||
|
Loading…
Reference in New Issue
Block a user