From EurAsiaWiki

Jump to: navigation, search


The Free60 JTAG Hack

By tmbinc (aka Felix Domke)
This wiki is maintained by ModRobert

Main sources: and

Related downloads can be found using this search in the EurAsia download section.


There is a new hack which can boot homebrew code in less than 5 seconds. See
at the end of this document for a description how the hack works. For now,
all we need to know is that this is a new way to exploit the well-known 4532
kernel, in a way which also works on updated machines, unless they have been
updated by the summer '09 update. It also works on all hardware types.

This document is a technical description meant for people who want to
undestand the hack. If you don't understand a word, calm down - there
probably will be future releaes, howtos etc.

Please also notice that from a functional side, the result will be the same
as the KK-hack; it's just must faster, works on more hardware and is more
reliable. So it replaces the KK-hack, not less and not more.


First, determine your kernel version. This hack has been verified to work
until the 849x-update (summer 09).

Determine your hardware type, which is either a Xenon (no HDMI), Zephyr
(HDMI, but 90nmCPU/80nm GPU), Falcon/Opus (60nm CPU) or Jasper (new
Southbridge, 60nm GPU, 60nm CPU).

You need some files, which are not part of this package. We are still
working on proper, legal ways to obtain these files, for example by
obtaining them from files you already have (like a NAND backup).

You need:

 - A suitable "CB/CD pack". This is a part of the bootloader, and you need a
   specific version for your hardware type:

Xenon: 1921
Zephyr: 4558
Falcon: 5770
Jasper: 6712

(Especially on Xenon, you might be able to use an older version, too. But
the newest one will work in any case.)

 - A hacked SMC code, _for your hardware type_.
 - Either a Microcontroller doing the JTAG stuff, or a hacked SMC with JTAG
 - The 4532 kernel update, extracted (you need the xboxupd.bin)
 - A binutils cross toolchain to target the ppc64 arch
 - A compiled payload, like XeLL

 - A possibility to reprogram the NAND flash. You can use an external
   programmer, a SPI programmer (which will be released soon), or some
   dedicated hardware.

Building a suitable image

In order to produce an image suitable for the attack, let's reconsider what
we need:

 - A patches SMC firmware, which starts the CMD 07 "READ SECTOR(S) DMA" at
   the right time. Note that you need to use the right SMC based on your
   machine type. Yes, they are all different. Running a pre-jasper code on a
   jasper-southbridge is particulary difficult to recover from. Be warned.
 - A microcontroller firmware which does the JTAG thing, implemented as a
   SMC patch.
 - A 2BL/4BL combination suitable for your machine type, with version 1920
   or up.
 - The 5BL (1888 base kernel), which is always the same binary.
 - The 4532 (or 4548) patch, extracted from the 4532/4548 system update.
 - An SMC config block, which stores some boring SMC-related data.
 - Our exploit buffer, which is DMA'ed into the kernel/HV
 - The code we want to run (XeLL, for example)

The can build a flashrom image if you give it the right


python image_backup.bin input/C{B,D}.1920 input/4532_upd.bin 
 input/xell-backup.bin input/xell-1c.bin input/smc_hacked.bin

 - image_backup.bin is your original nand content,
 - C{B,D}.1920 are a suitable 2BL/4BL, in decrypted form
 - 4532_upd.bin is the xboxupd.bin from the 4532 update,
 - xell-1c.bin and xell-backup.bin are XeLLs linked to 0x01c00000
 - smc_hacked.bin is the SMC with the hacked read rtc handler (and possibly
   also the jtag stuff)

Multiple parts of the image will be generated in the output-directory. You
need to flash them all, at the proper positions.

Flash this images into the 360 NAND flash. Needless to say, MAKE AN UPDATE
FIRST= Also, remove R6T3! There is code out which can burn fuses, and=
potentially render boxes unusable. By removing R6T3, this won't be an issue
anymore. Add the 3 resistors if you want to use the SMC-based JTAG hack.

Connect a VGA cable, and power on the box. If you're greeted with a blue
XeLL screen, then congratulations, everything is fine= Have fun!=


So we need some hardware which uses JTAG to set the DMA target address soon
in the bootup sequence, as long as JTAG still works. We started using an
external microcontroller, but we already HAVE an on-board microcontroller -
the SMC= There are some leftover GPIO ports, which are - at least on=
Xenon-boards - easily accessible on the left. They operate at 3.3V, so we
need some resistors to handle the 1.8V logic level of the GPU.

Zephyr and up don't have so many GPIOs available anymore, but don't
worry, we found a solution there, too.

In case you are using the hacked SMC with the GPIO, please use 330 Ohm
resistors to connect

J1F1.3 --- [[330R]] --- J2D2.1
J1F1.4 --- [[330R]] --- J2D2.2
J1F1.5 --- [[330R]] --- J2D2.4

How does this all work?

To understand this new hack, let's first look at what made the KK exploit
possible: A fatal bug in the Hypervisor's Syscall Handler, introduced in the
4532 kernel update. For more details, take a look at which explains
the problem in great detail.

The KK exploit exploited the kernel bug by modifying an unsigned shader to
do a series of so-called memory exports, an operation where the GPU can
write the results of a pixel or vertex shader into physical memory. The
shader was written to overwrite the Idle-thread context to make the kernel
jump at a certain position in memory, with some registers under our control.
In order to control all registers, a second step was necessary, this time by
jumping into the interrupt restore handler. This finally allows all
CPU general purpose registers to be filled with determined values. The
program counter could be restored to a syscall instruction in the kernel,
with register values prefilled so that they would trigger the exploit.

The exploit basically allows jumping into any 32-bit address in hypervisor space.
To jump into an arbitrary location, we just used a "mtctr, bctr"-register
pair in hypervisor, which would redirect execution flow into any 64-bit
address. This is important, since we need to clear the upper 32bit (i.e.,
set the MSB to disable the HRMO), since the code we want to jump to is in
unencrypted memory.

This code would usually load a second-stage loader, for example XeLL, into
memory, and start it. XeLL would then attempt to catch all cpu threads
(because just the primary thread is affected by our exploit), and load the
user code, for example from DVD.

So, the following memory areas are involved:

 - Idle Thread context, at 00130360 in physical memory

This stores the stack pointer (and some other stuff) when the idle thread
was suspended. By changing the stack pointer, and then waiting for the
kernel to switch to the idle thread, the stack pointer can be brought into
our control. Part of the context switch is also a context restore, based on
the new stack pointer.

 - Context restore, part 1, arbitrary location, KK expl. uses 80130AF0

The thread-context restore doesn't restore all registers, but let's us
control the NIP (the "next instruction" pointer). We setup NIP to point to
the interrupt context restore, which does a SP-relative load of most

 - Context restore, part 2, same base location as part 1

We just re-use the same stack pointer, because the areas where the first
context restore and the interrupt context restore load from do not overlap.
The second context restore allows us to pre-set all registers with arbitrary
64 bit values.

 - The HV offset, at 00002080 for syscall 0x46 on 4532

Because of the HV bug, we can write this offset into unencrypted memory,
giving us the possibility to jump into any location in the hypervisor space
(i.e. with a certain "encryption prefix"). We usually write 00000350 here,
which points to a "mtctr %r4; bctr" instruction pair in hypervisor, which
lets us jump to %r4.

 - Our loader code, at an arbitrary location

This code will be executed from hypervisor. It's the first of our code which
will be executed. %r4 on the syscall entry has to point to this code.

Only the the idle thread context and the HV offset have fixed addresses.
It's easily possible to merge this so that only two distinct blocks needs to
be written into memory, but it's not possible to merge this into a single

Fortunately, the NAND controller allows doing DMA reads where the payload
data is split from the "ECC"-data. Each page has 512 bytes of payload, and
16 bytes of ECC data. Thus, a single DMA read can be used to load all
required memory addresses. We chose the Payload to read the Idle Thread
Context, the Context Restores and the loader code. The ECC data will carry
the HV offset.

To to a DMA read, the following NAND registers need to be written:

ea00c01c Address for Payload
ea00c020 Adresss for ECC
ea00c00c address inside NAND
ea00c008 command: read DMA (07)

The System Management Controller (SMC) is a 8051 core inside the
Southbridge. It manages the power sequencing, and is always active when the
Xbox 360 has (standby or full) power applied. It controls the frontpanel
buttons, has a Realtime clock, decodes IR, controls temperatures and fans
and the DVDROM tray. It talks with the frontpanel board to set the LEDs.
When the system is running, the kernel can communicate with the SMC, for
example to query the realtime clock, open the dvd-tray etc. This happens
over a bidirectional FIFO (at ea001080 / ea001090). See the XeLL SMC code
for details.

The SMC can read the NAND, because it requires access to a special NAND page
which contains a SMC config block. This block contains calibration
information for the thermal diodes, and the thermal targets etc. The 8051
core has access to NAND registers, which are mapped into the 8051 SFRs. It
uses the same protocol as the kernel uses, so it writes an address, does a
"READ" command, and then reads the data out of the "DATA" registers.

It could also do a "READ (DMA)"-command. So by hacking the SMC, we could
make the box do the exploit, without any shader - the SMC can access the NAND
controller all the time, even when the kernel is running (though it will
likely interfere with the kernel). So, just we just trigger the DMA read
when the kernel has been loaded, and everything is fine.


Well, that would be too easy. While most NAND registers are mapped, tyhe DMA
address registers (1c, 20) are not. We can DMA, but only to the default
address of zero (or wherever the kernel last DMAed into). Fail.

The GPU, the (H)ANA (the "scaler" - which in fact doesn't scale at all, it's
"just" a set of DACs, and, since Zephyr, a DVI/HDMI encoder), the
Southbridge and the CPU have their JTAG ports exposed on the board. They are
unpopulated headers, but the signals are there. CPU JTAG is a different
(complex) story, and SB JTAG doesn't offset much funcationality. ANA JTAG is
boring since the ANA doesn't sit on any interesting bus. That leaves GPU

GPU JTAG was reverse-engineered until a point where arbitrary PCI writes are
possible, up to a certain point. So that makes it possible to talk to each
PCI device in the system, including the NAND controller. So we can simply
use THAT instead of the SMC to start the DMA?


Well, not quite. The problem is that the "VM code", the code which does a
lot of system initialization, like the memory (that code is also responsible
for generating the 01xx "RROD"-Errors), sets a certain bit in some GPU
register, which disables the JTAG interface. The VM code is executed way
before the kernel is active. So this is fail, too.

But the combination works - by programming the DMA target address via JTAG,
and launching the attack via SMC. The attack can be launched as soon as the
kernel is running, and quite early, it does query the SMC for the RTC. We
abuse this call to start the attack instead, which is a perfect point for

But how do we run an exploitable kernel at all? Most machines are updated
already. Let me refresh your knowledge about the boot process again:

1BL (Bootrom)

Buried deep inside the CPU die, this ~32kb of ROM code is responsible for
reading the 2BL from NAND-flash and decrypts it into the embedded SRAM in the
CPU. It verifies the hash of the decrypted image with a signed block at the
beginning of the 2BL, and will stop execution of this hash mismatches. This
code also contains a number of test functions, which can be activated by
pulling the 5 "POST IN"-pins, which are available on the backside of the
PCB. None of these tests looks particulary interesting (from an exploitation
perspective) - they mostly seem to be related to the FSB (the bus between
CPU and GPU). This code is fixed, and all systems use identical code here.

2BL ("CB")

This code is usually located at 0x8000 in NAND flash. It's decrypted by 1BL,
and runs from internal SRAM.

It does a basic hardware initialization, and contains the "fuse check code",
which verifies the "2BL version". The fuses store the expected version.
The 2BL stores a "Version" and a "AllowedMask" (=bitfield), and
this is usually stored at address 0x3B1 / 0x3B2..0x3B3.

       Xenon            Zephyr     Falcon            Jasper
2 0003 1888, 1901, 1902
4      1920                                                 "new zeropair code"
5 0010 1921             4558       5760,5761,5770    6712        TA-fixed

It then verifies the pairing information stored in the 2BL header. Part of
this verification is a checksum check of the NAND area which was used to
load the SMC code from.

It also contains a virtual machine and some
code to run on this machine. The virtual machine code, which is pretty
complicated, does the following things:
 - Initialisation of the PCI-Bridge
 - Disable the GPU PCIE JTAG test port
 - initialize the serial port
 - talk to the SMC to clear the "handshake"-bit
 - initialize memory
 - hopefully not: generate RROD if memory init fails

After that, the external (512MB) memory will be initialized and usable. 2BL
then decrypts the 4BL into this memory. Memory encryption will already be
enabled - no executable code is _ever_ written unencrypted.

4BL ("CD")

This code is responsible for checking and unpacking 5BL, as well as applying
update patches. First, the fuses are read to determine the console "Update
Sequence", a number which basically counts the number of updates installed.
Since updates are, in the same way as 2BL, paired to a console, this allows
to configure the console in a way that no old update will be used. So each
update slot stores the maximum value of burned fuses (well, essentially the
exact value). The base kernel also has an associated value, usually zero,
but this can be changed in the 2BL pairing data block. This is what the
timing-attack increments, in order to revert to the 1888 kernel.

5BL ("HV/Kernel")

The HV and kernel are merged into a single image, which is compressed with a
proprietary algorithm (LDIC).

6BL ("CF"), 7BL ("CG")

This is part of a system upgrade. Each console has a so-called "Base
Kernel", which is the 1888 kernel which was available on launch back in
2005. Then there are two "update slots" - areas of 64k each (128k on
Jasper), which contain a 6BL and 7BL. 6BL is code which applies the
update, using a clever delta-compression. 7BL is the actual delta-compressed
update, essentially a binary diff.

Oh, updates are >64k. So only the first 64k are actually stored in the
update slots, the rest is stored in the filesystem as a special file. Since
6BL doesn't contain a filesystem parser, a blockmap is added in 6BL which
points to the sectors which contain the rest of the update.


Now there is a special situation: If the 2BL pairing block is all-zero, the
pairing block will not be checked. However, a bit is set so that the kernel
doesn't boot the dashboard binary, but a special binary called
"MfgBootLauncher", where "Mfg" probably stands for "Manufacturing". So this
is a leftover of the production process, where the flash image is used on
all hardware, probably also before any CPU-key has been programmed.

By abusing this feature, this allows us easily to produce a flash image
which runs on all hardware. However, 4BL won't look at update slots when it
detects this mode, so we end up in the 1888 base kernel. And we can't run
the dashboard, so it's impossible to escape this mode.

Previously, this has been deemed very uninteresting, because first the 1888
isn't exploitable by the KK exploit, and second because it's impossible to
run the KK game anyway.

However, starting with 2BL version 1920, an interesting thing happened:
The encryption key for 4BL is generated with the help of the CPU-key now.
That means that without the CPU-key, it's not possible to decrypt the 4BL
anymore. Note that each 2BL has exactly a single valid 4BL binary - 2BL
contains a hardcoded hash for the 4BL, and doesn't use RSA.

However, zero'ed pairing data is detected, the CPU-key is NOT used in this
process, like it was previously. That also means that you cannot just zero-out
the pairing data anymore - the 4BL would be decrypted with the wrong key
then. Instead you need to decrypt the 4BL (which requires knowing the CPU
key), and re-encrypt it with the old algorithm.

However, 1920 was suspecible to the timing attack - so a CPU-key recovery
was possible on one console, which allowed us to decrypt the 1920 4BL. That
4BL shows a very intersting change: Whenever zero-pairing is detected, the
update slots are not ignored anymore. Instead, if the update-slots are
zero-paired as well, they are applied.

This change allows us to boot any kernel, provided we have a (1920 and up)
2BL/4BL set which runs on that machine. This is very important, because we
can build up an image now which runs into the 4532 kernel, regardless on how
many update fuses are set. However, the 2BL revocation process must be
passed, so we are not completely independent of the fuses, still. But since
we use zero-pairing, the SMC hash doesn't matter anymore (there are other
ways to work around the SMC hash problem, like the TA, but we get this for
free). Still, we boot into the MfgBootLauncher (into the 4532 version now,
which does a red/green blinking thingie - you'll notice once you see it,
it's very unique and doesn't look like any RROD or so). But thanks to the
SMC/JTAG hack described above, this allows us to launch our attack from this

Newer consoles (which have the TA fix) don't run 1920 anymore. They run, for
example, 1921. The problem is that we cannot run HV code on these machines,
so we don't know the CPU key. However, when comparing the 1921 and 1920 2BL
(which we can still decrypt), the only change is the addition of the timing
attack fix (i.e. replacing two memcmp instances with a memdiff function).
Also, we know the expected hash value of the decrypted 4BL. Based on a 1920
4BL, and the guess what has changed functionally, and the new size of the
4BL, we were able to guess the modifications, which yields an image which
passes the 2BL hash check. Note that this is not a hash collision - we did
merely derive the exact image by applying the changes between 1920 2BL and 1921
2BL into 1920 4BL, yielding the 1921 4BL.

The 1921 2BL theoretically runs on all machines so far, even TA-proof ones.
But it crashes on Zephyr, Falcon and Jasper. The reason is the VM code,
which doesn't cover the different GPUs (Xenon has 90nm GPU, Zephyr and
Falcon have 80nm, Jasper has 60nm, so there are 3 GPU revisions in total).

But the step from 1921 to, say, 4558, is even smaller. It's just the
different version number, plus a slight difference in the memcpy code, which
again can be ported over from 2BL.

Jasper's 67xx is a different thing, since this code adds support for the
largeblock flash used in "Arcade"-Jasper units. We have used some magic to
retrieve this code.

So we now have ALL 4BL versions. Isn't that great? It means that ALL
machines can run the 4532 kernel. The good news is also that the 4532 kernel
supports falcon consoles, and runs long enough to also work on jasper
consoles (because we exploit way before the different GPU is touched at


Q: "The power supply goes red when plugging in power="=
A: You shorted a power pin, probably V33_SB, the one attached to the NAND
   flash. Carefully look for solder residues. Use a lot of flux and a
   properly-heated soldering iron.

Q: "The power supply stays yellow when I press the power button, and nothing
    else happens."
A: The SMC code is invalid. This can be a misconnected flashrom, an illegal
   image, a bad flash or simply a bad SMC code.
     - Electrical connections first.
     - Did you flash with the proper ECC settings? The flash images we are
       working with usually contain raw ECC information, i.e. 512+16 bytes per
       sector. Make sure your flash programmer is not modifying these 16
       bytes, but writing those as they are.
     - Have you used the right SMC image?

Q: "The fans run at full speed immediately."
A: This is very likely a bad SMC config sector. Did you flash all the parts
   generated by the image creation tool at the proper position?
   Note that offsets are given as payload offsets, not counting ECC bytes.
   Usually this matches what your average NAND programmer tells you, but in
   case you re-assembled these into a single image, take care to properly
   convert the offsets.

Q: "I get E79"
A: This means that, congratulations, your console is still booting into a
   kernel, and just cannot go further (which was to be exepcted, given that
   there is no filesystem anymore).
   You're almost there, but for some reasons, the DMA attack didn't run.
   This can be either that you didn't used a patched SMC, or that the target
   address wasn't inserted properly.

Q: "Console powers on, but I get a black screen."
A: Well, there are many reasons here again. First, wait some time (~1
   minute), and see if you get a RROD. If you do, the VM code failed to
   handshake with the SMC (error code XXXX), which usually means that it
   crashed, and the SMC watchdog triggered until it retried too often.
   Did you use the proper 2BL/4BL image for your machine type? Did you use a
   recent enough SMC version? Since the VM code took more and more time
   (from roughly a half second in 1888 to several seconds in 1920), the SMC
   code was modified to time out later. Be sure to use a known-good SMC
   version, if possible, based on the version which was installed before.
   If you don't get a RROD, please try checking your POST code. You can do
   this via CPU jtag, or by measuring the 8 POST pins.

   Post code 6C:
   The exploit failed, somehow.

   Post code 10:
   Our code is running= That's great, but it failed copying the XeLL-payload=
   from flash. Try booting into the alternate loader (see below in the
   "exploit loader" section), or reflash.

   Post code 11:
   Exploit code ran, and jumped into XeLL. XeLL crashed. Try alternate
   loader, or do serial upload for recovery, if you really screwed up both the
   primary and secondary loader. (You failed, in that case.)

   Post codes >= 0x80:
   Those are errors from the bootloader. Please check the disassembly of
   those loaders to see what's wrong exactly. It shouldn't happen unless you
   have a bad flash.

   Post code 0xA0:
   Your 2BL didn't want to run on your hardware due to the 2BL revocation
   fuses. Use a more recent 2BL/4BL set for your hardware. If you're already
   running {1921, 4558, 5770, 6712} then  you're out of luck. Your box was
   already updated to a newer 2BL, which likely fixed what we used to
   exploit. Restore R6T3, restore the flash image, and use this console for
   playing games. Get another console, and try again.

Please note that some hardware elements are not properly initialized at the
early time of the exploit. This affects:

 - The CPU is initialized in low-power mode, where it runs at quarter-speed.
   Setting the CPU power mode is possible, of course, but needs to be
   reverse-engineered from the corresponding hypervisor syscall.

 - A full screen setup is required, including the programming of the
   ANA-chip. Code is available for setting up a 640x480 VGA mode, support
   for other resolutions needs to be added.
 - EDRAM must be "trained". This is what fails when the E-74 error is
   displayed. The code is rather complex, and has been
   reverse-enginnered, but doesn't run properly yet. However, it has been
   shown to work a bit, and can likely be tweaked to work properly.

 - SATA likely needs some reset sequence. Linux kernel does this fine, but
   XeLL doesn't work.

All of these issues are expected to be fixed.

This hack can also be used to reboot into a Microsoft kernel, in order to keep the
possibility of playing games locally. This is not within the scope of this
document, and is actually not related to this hack at all. This hack allows
you the execution of software - and YOU decide what software that should be.
It could be linux, your favourite emulator, or a rebooter.

Note that we do not support patching the Microsoft kernel for piracy
under any circumstances. Also, playing on LIVE with a modified console
won't be possible without getting banned, ever. There are already
challenges in place which detect any unauthorized modification. We urge you
to not abuse this hack for piracy.


The first own code which is executed is a small loader, which operates in
the following way:

 - If a character is present on the serial port, it will be read.
   - if that character is '@', we will enter serial upload mode.
   - if that character is ' ', we will use the backup bootloader
 - if not serial upload mode:
   - POST 0x10
   - read bootloader from flash (either backup or normal)
   - POST 0x11
   - run
 - serial upload mode:
   - output '>'
   - receive characters
   - after 10 consecutive 'x', stop upload
   - output '='=
   - run

This allows some kind of recovery if you want to update the in-flash

The used addresses are the following:
  FLASH_BASE is the location in flash of the backup bootloader,
  FLASH_BASE + 0x40000 is the location of the main bootloader,
  CODE_BASE is the memory address of the bootloader in ram.

By default, the following memory map is used:

00000000..00100000: SMC, KV, CB, CD, CE, CF, CG, backup bootloader
00100000..00140000: main bootloader
00140000..00f7c000: empty space
00f7c000          : smc config block
00ffc000          : exploit buffer

But this can be tweaeked.


A lot. First, thanks to all of you which have been working on Xbox 360
reverse engineering. Thanks to everybody involved in technical discussions

(in order of appearance)
recovery of CB1920 by robinsod,
initial JTAG reverse enginneering by tmbinc,
getting importants facts straight by SeventhSon,
first description of how it worked out by Martin_sw,
SMC JTAG code, lots of testing and debugging by Tiros


Source: tmbinc @

As a first step toward a "release", I've committed the tool to build an image suitable for the hack, as well as some additional information and a description of "how it works". You can find that work in the repository:;atree;f=imgbuild

I understand that not all of the required binaries are available right now, but we'll work on provider ways to derive them from nand dumps. But those of you who are able to recover the required binaries should be able to build an image which boots right into xell.

There are 3 things that we have to take care about: - The 1920+ CB/CD. If somebody has a 1920 box, just do the timing attack, extract your cpu key, add that cpukey into "decrypt_CD", and use that image. You'll get the decrypted CB/CD in your "output"-directory. I'll then describe how to build the 1921 and the other CDs from that. - the hacked SMC for kicking off the read. You basically need to add writing to the nand command register in command 04. The command you need to write is 07. I can explain this more, but there are people who understand the SMC code much better than I do, so maybe they can drop in here. - the SMC JTAG stuff, which Tiros wrote, so you only need to add resistors instead of a uC.

The SMC Hack, part 1 (DMA read)

Source: tmbinc @

Ok, here is a quick howto on patching the SMC code. First, remember that the SMC code is in NAND form 0x1000 to 0x4000 (usually), and that it's encrypted but can be trivially decrypted. the imgbuild script will output the decrypted SMC for you. This is 8051 code, and is the code which in charge of booting up the CPU, as well as being in control of some hardware elements. The CPU can talk to the SMC over PCI-e, so there is a "command handling" inside the code. There are multiple SMC versions (even multiple for one board type), but using any SMC which was made for your board type should be fine (i.e. the revision doesn't matter much, but it's important that it was made for your board type, i.e. Xenon/Zephyr/Falcon/Jasper).

The hack goes as the following:

Right in kernel start, the kernel will query the RTC from the SMC. This is command 04, which is sent over the ea00108x registers. in SMC, approx at offset 0x836 (this differs from SMC version to version), there is code like (pseudo-code to avoid pasting disassembly)


if (A = 1) goto CMD_01;
else if (A = 4) goto CMD_04;
else if (A = 7) goto CMD_07;
else if (A = 0xa) goto CMD_0A;
else if (A = 0xF) goto CMD_0F;

follow the CMD_04. The function ends with a series of "mov A, <somevalue>; lcall write_fsr_d5". This is the function we want to hack into, and we need to add the following function:

"mov FSR_F5, 7"

because FSR_F5 is the NAND_Command register (also reachable from ea00c0xx), and 7 is the "read physical page, DMA" command. Encoded, this is "75 f5 07", so we just overwrite the "E5 30 12 xx xx" before the "22" (ret) with "75 f5 07 22", i.e. "mov FSR_F5, 7; ret".

That's it.

Remaining thing is to have the JTAG setup. I'll cover this in another topic.

Info from redline99

This is just an example to get someone started, it is not meant as the smc patch that is needed, specifically this doesn't address using the smc to write jtag commands

Here are some great tools for working with the SMC bin file (there are also great for mtk dvd firmwares too...)

DIS8051 Cross-Disassembler V2.1

8051 Macro Assembler

Big tip here: learn the "org" statement that allows us to specify an offset to the assembler for our pieces of code and is really the key to making patches this way.

Assemble using: "asemw example.src" that will create an Intel hex file of this patch code only. That hex file can then be overlayed onto the smc.bin. There are tools for that "hexbinw.exe" in that asem-51 package.

Anyways the point of my post is that complex code can be written in assembler and automatically be applied the the bin file in minutes. You don't need to be super human and hex edit the bin file by hand. Tiros taught me all this years ago when I was interested in the TS-H943A firmware and it applies to the smc now too. Kinda cool= ;)=

free_space              equ        02DC0h         ;open space in the bin to place our new code
test_rtc                equ        00851h         ;Patch location to intercept test
check_next_cmd          equ        test_rtc+5     ;next test after query_rtc
query_rtc               equ        008ACh         ;function address for query_rtc
sfc_cmd_reg             equ        0F5h           ;SFR Address for SFC command reg

; Intercept query rtc condition test
        org         test_rtc
        ljmp        hack_trigger                  ;Call Main Payload SetupHook (smc cmd 0x4)

; Main Payload Section
        org         free_space
                                                  ;a = smc command byte
        cjne        a,#004h,not_cmd               ;0x4 = query_rtc smc cmd check
        ljmp        do_dma                        ;
        ljmp        check_next_cmd                ;<< Jump out >> Not command 4 (query_rtc)
        ;NOTE: This is only an example on how to setup for a trigger
        ;      the address registers still need to be setup prior to this (via jtag)
        mov         sfc_cmd_reg,#007h             ;0x7 = Data Physical Address Command (DMA transfer)
        ljmp        query_rtc                     ;<< Jump out >> It was command 4, so pass back
                                                  ;               to normal code path

        end                                       ;dont forget me :)

The JTAG setup

Source: tmbinc @

Here I want to describe the JTAG sequence which prepares the NAND controller a bit more. Please read the hack.txt before asking questions here, it's vital to understand this.

Remember that we cannot write the DMA target address from SMC, so we need to do this using JTAG. Most of this has been already discussed in the JTAG-thread, but let's reconsider what we need to write:

  write32(0xd0000018, 0x20100); // enable PCI bridge
  write32(0xd0140010, 0xea00c000); // enable BAR0 for nand controller
// (to appear in pci space at ea00c000)
  write32(0xd0140004, 0x6); // enable NAND, enable busmaster
  write32(0xea00c00c, PAYLOAD_BASE + 0x20000); // address of exploit buffer, in flash
// (we could write this in SMC, too, but it's easier here)
  write32(0xea00c01c, 0x00130360); // target address of main data
// (overwrites idle thread context and first stage exploit code)
  write32(0xea00c020, 0x00002080); // target address of ECC data, overwrites HV offset

We also need to take care that this happens soon enough, but not too soon, since we cannot interfere with the CPU. The way I first implemented this in an AVR microcontroller was to simply wait for the IDCODE to be valid, delay a bit, and then start the JTAG writes.

The support routines are like

static inline int j(int tdi, int tms)
  int v = 0;
  if (tdi)
    v ||= TDI;
  if (tms)
    v ||= TMS;
  set_bits(v || TCK);

  int res = (get_bits() & TDO);
  return res;

unsigned long long jtagn(int IR, unsigned long long val, int n)
  j(0, 0); // if we were in TLR, nop if we are in RTI already

  j(0, 1);
  j(0, 1);
  j(0, 0);
  j(0, 0);
  j(0, 1);
  j(0, 1);
  j(0, 0);
  j(0, 0);
  unsigned long long res = j_n(val, n);
  j(0, 1);
  j(0, 0);
    // and we are in RTI again
  return res;
static unsigned long jtag32(int IR, unsigned long val)
  j(0, 0); // if we were in TLR, nop if we are in RTI already

  j(0, 1);
  j(0, 1);
  j(0, 0);
  j(0, 0);
  j(0, 1);
  j(0, 1);
  j(0, 0);
  j(0, 0);
  unsigned long res = j_n(val, 32);
  j(0, 1);
  j(0, 0);
    // and we are in RTI again
  return res;

void write32(unsigned long addr, unsigned long data)
  jtagn(0xe0, 3 || addr || (0xFULL << 32), 36);
  jtag32(0xe1, data);
  jtagn(0xe4, 1, 1);

void jtag_doit(void)
  int i = 20;
  while (i--)
    volatile long j = 10000;
    while (j--);
  write32(0xd0000018, 0x20100);
  write32(0xd0140010, 0xea00c000);
  write32(0xd0140004, 0x6);
  write32(0xea00c00c, PAYLOAD_BASE + 0x20000); // address in flash of exploit

  write32(0xea00c01c, 0x00130360);
  write32(0xea00c020, 0x00002080);

static void TLR(void)
  int i;
  for (i=0; i<5; ++i)
    j(0, 1);

void main()
... hw init

  while (1)
    if (hack_state = 1) /_ hacked _/
      if (=is_valid_id(jtag32(0x50, 0)))=
        hack_state = 0; /_ poweroff _/
    } else
        /_ power off _/
      if (is_valid_id(jtag32(0x50, 0)))
        hack_state = 1;

Tiros did a great hack by adding this code into the SMC, so we just need to use the resistors to make the SMC able to speak to the GPU jtag.


Source: tmbinc @

I finally committed what i've been working on since some time into the free60 git repository ( It's aim is, together with the other parts there, to provide homebrew SDK, similar to what devkitPPC/libogc does for Wii.

I know that some people are not interested in this, so those people should simply ignore this. But other people could use this as a base to port emulators, media players, games etc.

Currently supported features are:

  • Memory management, so we have a easy-to-use 32bit memory map (with separate cached and uncached access to memory, uncached access to peripherals)
  • full GPU support based on my xenos-library
  • framebuffer setup, currently only 640x480 VGA
  • USB support, including mass-storage and HID
  • That also gives us input support from xbox controllers
  • basic PPC functionality like timebase, cache control
  • SMC, uart

I'm currently working on a snes9x port, which turned out to be rather easy. I'll post an alpha video, binaries and a source-diff tonight.

NandPro: LPT and USB nand flash programmer with only 7 wires

Source: Tiros @

Heads up!! File should be available soon ;)

Supported device interfaces:


  LPC2148 Olimex USB header board
High performance 16MB/2Mins
LibUsb driver


  Parallel Printer Port, SPP mode
Low performance, 16MB/35mins (cpu dependant)
Dlportio printer port driver

Seven connections must be made from MAINBRD to the HW device interface.

  MAINBRD connects as specified to either Olimex board, or a PC printer port.

SS EXT1-3 DB25.1 J1D2.2
MISO EXT1-6 DB25.11 J1D2.4
P0.28 XT2-1 DB25.16 J2B1.6
GND EXT1-26 DB25.18 J1D2.6 or J2B1.12
MOSI EXT1-7 DB25.14 J1D2.1
SCK EXT1-5 DB25.2 J1D2.3
P0.29 EXT2-2 DB25.17 J2B1.5

Some parallel ports run at 3.3v others at 5v. The MAINBRD is 3.3 volts. Testing with 5 volt lpt and NO resistors didn't burn anything up. YMMV :P It is recomnened to use 100 ohm series resistors for all lpt connections except for DB25.11 and DB25.18 (GND). This solution isn't perfect but you typically dont leave it hooked up forever anyway. If someone wants to design and post a buffer circuit go right ahead. I can't be bothered ;)

Diagram of CB/CD/Kernel/HW (Attackable/Exploitable/Compatible)

Source: arnezami @

Since there are quite a few combinations of hardware and Cx-sections that are (or are not) attackable/exploitable/compatible I thought I try to make a diagram of it.

I'm sure it isn't complete or fully correct yet, but it's a start. Here is a picture:


It's mostly the combinations of HW/CB/CD that I'm not sure about (most notably the dotted lines). Also the dash hardware compatibility (darker purple bars on the right) is still incomplete/imprecise.

Feel free to confirm, correct and extend it. I'll update this post when something needs adjustment.



PS. The light purple bars (on the right) indicate which kernel can be started for a given type of HW (needed for the jtag exploit). That is start up to POST 0x6C.

I've moved CB 1922-1940 and added CB 7373 to the lower part. Also added full kernel+dash falcon support for 4532. Not sure about ful kernel+dash zephyr and jasper support for 4532. Removed the dotted lines since there is less doubt now.

CD.1920 -> CD.1921

Source: tmbinc @

One of major - solved - roadblocks in this hack was that the 1921 CD binary was not available in decrypted form. That was solved by disassembling the 1920 CD, and applying the changes from 1920 CB to 1921 CB (basically, the timing-attack-fix).

Since I can't just post the assembly source here (after all, it's MS code), I've built a tool which can turn a 1920 CD into an 1921 CD (so it needs the 1920 CD, and the 1921 CB for the new code pieces)

It's available on;ablob_plain;f=imgbuild/

It can also build Zephyr and Falcon CDs. It cannot build Jasper CDs.

This should allow you to create a hack-image with the 1921 CD. Keep in mind that the current requires updated SMC code to read from 0x200 instead of 0xffc000. You can patch that at the end of the SMC code; look for "ea 00 c0 0f 00 xx yy zz", and make xxyyzz=0x200 (instead of 0xffc000).

XeLL update

Source: tmbinc @

When a XeLL update comes, you don't need to attach your LPT flasher again if you can use the integrated xell update.

But please be aware: The update feature as added on August-31th, so if your XeLL is older than that, you won't be able to do the update. In this case, you need to flash a new image.

Also, you need a recent image which can be updated. All image created with a prior to August-23th cannot be updated. In this case, you also need to flash a new image.

If you have a recent enough xell/image, then grab the xell binary. There should be one up from today on xbins, but you can also compile your own. (In that case, grab the file "xell-1f.bin", i.e. the same file you would use to produce an image)

Rename the file to updxell.bin, and put it on a FAT-formatted USB stick which is supported by the currently installed xell version. Remove (or rename) the xenon.elf, that file must not exist.

Put in the USB stick, and powerup the box. Xell will display

* found XeLL update. press power NOW if you don't want to update.

and then wait for 15s. After that, the update will be started. If you want to abort, just switch of your box.

There might be a number of reasons why the update wouldn't work. Let me list the most probable failures:

- "* try booting tftp" XeLL couldn't find the updxell.bin file on the USB stick, either because it didn't support the filesystem (must be FAT16/FAT32), or because XeLL didn't support your usb sticks at all (previous xells had a problem here) - " * unknown hackimage version." Your hackimage isn't supported. Usually that means that it is too old, meaning you first need to do a full reflash. - " * relocating sector yyyyyyyy to xxxxxxxx..." That's completely normal, and should not interrupt the update.

Otherwise, it should say " * update done" and then you can reboot the box.

In case updating went bad (for example, if updxell.bin was broken etc.), there is a way to boot back into the "backup xell" (there are two xell versions in flash, the normal one, and the backup one.) Usually the normal xell is started, but you can start the backup one by either: - Attaching a wired controller on the back USB port, and pressing the X button to powerup the box, or - Pressing the windows-button on a remote control to powerup the box.

In both cases, the backup xell will be started instead, and you can re-try the update. Note that xell will never touch the backup xell, it will always just reflash the normal one.

If you need to flash a new hackimage, and don't want to attach LPT/USB, the easiest way is to boot into linux, and use "lflash". But please only do that if you know that LPT/USB flashing works ok.

Speaking of the new XeLL, the following fixes were done in the 2009-09-11 release: - Console border when using SD - fixing a lot of USB sticks which didn't work before

Xmenu dashboard

Source: XanTium @ via hitman43 @
Official site:

Cpasjuste released the first public version of Xmenu for the free60 XeLL JTAG hack. It's a GUI .ELF Loader (a basic dashboard if you want) that can be used to load other libxenon homebrew software on your Xbox 360.

Xmenu 0.3
Xmenu is an elf loader with a basic gui.

Copy the file xenon.elf and the "xenon" folder to the root of your usb disk/pen.
Load it with the hack.

Version 0.3 :
- It's now possible to load custom icons. Put a ".png" image (32 bits, with alpha channel, 32*32 pixels would be better)
alongside your executable file, with the ".ico" extension. Example :
If you have an executable named "snes9x.elf", put the ".png" icon in the same directory with the name "snes9x.ico".
Version 0.2 :
- Graphics data is now loaded at startup, allowing to customise.
- Smaller fonts, this allow more items to be displayed.
Version 0.1 :
- Alpha testing version.

Linux device driver for xbox 360 audio

Source: jc4360 @

I am releasing the first version of linux device driver for xbox 360 audio. you can get source from here: The device driver is alsa compitable, so basically you can compile mplayer and then it should play various music formats for you easily. It supports both analog stereo and digital spdif (only dobly digital by now). Thanks for tmbinc for his finding on 360 audio hardware details and his help on debuging the code. The license for the code is GPL.

In order to compile it, you will need to properly edit sound/pci/Makefile with the following statements, and also change Kconfig if needed. do not forget to enable ALSA support in your kernel.

snd-xenon-objs := xenon_snd.o
obj-$(CONFIG_SND_XENON) += snd-xenon.o

To compile mplayer, download MPlayer-1.0rc2.tar.bz2 and edit libmpcodecs/ad_hwac3.c by applying the following patch:


--- ad_hwac3.c  1969-12-31 19:15:52.000000000 -0500
+++      1969-12-31 19:15:17.000000000 -0500
@@ -144,4 +144,17 @@

+static inline unsigned short bswap16(unsigned short a)
+      return ((a&0xff)<<8) || ((a&0xff00)>>8);
+static inline void mem_swap16(void *buf, int line)
+    int i=0;
+    uint16_t _buf16 = (uint16_t _)buf;
+    for (i=0; i<line/2; i++)
+        buf16[[i]]=bswap16(buf16[[i]]);
 static int decode_audio(sh_audio_t _sh_audio,unsigned char _buf,int minlen,int maxlen)
@@ -177,4 +190,6 @@
     memset(buf + 8 + len, 0, 6144 - 8 - len);

+    mem_swap16(buf, 6144);
     return 6144;
@@ -375,4 +390,6 @@
   memset(&buf[[fsize + 8]], 0, nr_samples _ 2 _ 2 - (fsize + 8));

+  mem_swap16(buf, nr_samples _ 2 _ 2);
   return nr_samples _ 2 _ 2;

To test:

-bash-3.2# aplay -l
____ List of PLAYBACK Hardware Devices ____
card 0: AudioPCI [[Xenon AudioPCI]], device 0: Xenon Audio [[Analog]]
  Subdevices: 0/1
  Subdevice #0: subdevice #0
card 0: AudioPCI [[Xenon AudioPCI]], device 1: Xenon Audio [[Digital]]
  Subdevices: 1/1
  Subdevice #0: subdevice #0

stereo music:
./mplayer -ao alsa:device=hw0.0 music.mp3/ape/flac/wav

digital music:
./mplayer -ao alsa:device=hw0.1 -ac hwac3 music.ac3
./mplayer -ao alsa:device=hw0.1 -ac hwdts music.dts

Please feel free to improve this driver for the following things: 1) Interrupt: I could not get pci interrupt to work. This driver currently uses a timer interrupt. 2) DTS passthrough: my receiver could not decode the raw dts bit stream sent by mplayer, I guess one register was not set correctly for dts passthrough. If you have a jtag setup on xbox 360 motherboard, you could help on this: put a dvd movie with dts track into 360 drive and play(check if your receiver receive dts signal), read 64 bytes from address 0xea001600 with your jtag device and then post the result here. 3) Mixer such as volumn setting etc.

The driver may not be bug free. I am not responsible for any damge that the driver may cause to your hardware, so use it at your own risk.

Free60 JTAG Hack for Falcon motherboards released

Source: README @ falcon_hack_1.rar

Finally the Falcon JTAG Hack is here :)

This is newest XELL (compiled 05.10.09) inserted into 5770 Falcon-Kernel.

Don't wonder about the Filesize, its correct like that. It just flashes the beginning of the NAND so your console specific data like MAC adress will stay.

Of course you should have a working backup of your NAND before you proceed.

Just flash with:

LPT nandpro lpt: -w16 falcon_hack.bin 0

USB nandpro usb: -w16 falcon_hack.bin 0

SMC-JTAG Hack Wiring

DB1F1 ---||<||--- J2D2.1 RFUnit 2nd row, 2nd Pin ---||<||---- J2D2.2 J2D2.4 --------- J2D2.7


Free60 JTAG Hack for Zephyr motherboards released

Source: README @ zephyr_hack_updxell.rar

Finally the Zephyr JTAG Hack is here :)

This is XELL (compiled 11.09.09) inserted into 4558 Zephyr-Kernel.

Don't wonder about the Filesize, its correct like that. It just flashes the beginning of the NAND so your console specific data like MAC adress will stay.

Of course you should have a working backup of your NAND before you proceed.

Just flash with:

LPT nandpro lpt: -w16 zephyr_hack_updxell.bin 0

USB nandpro usb: -w16 zephyr_hack_updxell.bin 0

SMC-JTAG Hack Wiring

DB1F1 ---||<||--- J2D2.1 RFUnit 2nd row, 2nd Pin ---||<||---- J2D2.2 J2D2.4 --------- J2D2.7


Free60 JTAG Hack for Jasper motherboards released

Source: README.txt @ jasper_6712_hack.rar

Finally the Jasper JTAG Hack is here :)

This is XELL (compiled 11.09.09) inserted into 6712 Jasper-Kernel.

Don't wonder about the Filesize, its correct like that. It just flashes the beginning of the NAND so your console specific data like MAC adress will stay.

Of course you should have a working backup of your NAND before you proceed.

___ NOTE ___

Only work with 16mb version, a fix may come out.

___ NOTE ___

Just flash with:

LPT nandpro lpt: -w16 jasper_6712_hack.bin 0

USB nandpro usb: -w16 jasper_6712_hack.bin 0


Personal tools