X-Pi, an xbox modchip using a Raspberry Pi

Discuss your Halo 2 mod project here.
Post Reply
User avatar
Grimdoomer
Admin
Posts: 1835
Joined: Sun Dec 09, 2007 9:09 pm

X-Pi, an xbox modchip using a Raspberry Pi

Post by Grimdoomer »

So I've been playing around with my Raspberry Pi's for a while now making all sorts of cool stuff. I've been tossing around the idea of seeing if I can make a modchip using the raspberry pi to feed the console a BIOS image over the LPC port. So I decided to start working on it earlier today. I'll post my progress here, and if everything works out in the end I will post schematics and code needed to reproduce it. This is really just a test to see if I can do it and if it will work, I'm not trying to do anything new here.

My end goal is to be able to feed the console a BIOS image of choice through the LPC port using a raspberry pi. Essentially I want to be able to SSH into the pi, run a script/program and give it the file name of the BIOS image I want to boot. It will then boot the console into that BIOS image.

Background
For those of you who don't know how the xbox loads alternate BIOS images from your modchips this part might be of interest. If you are already familiar with the process then this section can be skipped.

So how do xbox modchips work? Well the xbox console has a debug port called the LPC port on the motherboard. LPC (Low Pin Count) is an interface used to connect legacy peripherals and boot ROMs to the cpu of a computer. If you have ever opened your xbox console you might have seen this port. This is the LPC port, and most modchips will attach to it.

The port is activated when a certain pin (D0) on the motherboard is pulled low (grounded). When the xbox boots and sees that the D0 line is pulled low, it knows to load the BIOS from the LPC port rather than the onboard flash chip. The modchips in your console will wait for the LPC port to become active and then feed the BIOS image to the console using the protocol as specified by the LPC specification. Once the image has been read the console will attempt to boot into it.

The first generation of modchips were nothing more than a replacement flash chip that supported LPC. Yup, a single chip with a couple of wires soldered to it, nothing more. It was called the Xbox Cheapmod.

What I want to try and do is have the Raspberry Pi act as a LPC device and feed the console a BIOS image from a file on the Pi's SD card.

Step 1 - Preparing the console
Before I can even start playing around with the LPC port I needed to do some preparations. The Raspberry Pi must be fully booted before the xbox console is turned on, which means I need to tap a 5v power line that is powered at standby. I will also want a way to turn the console on and off via the Pi to make testing easier. Lastly, I will need to tap the D0 wire to make the LPC port active.

I was able to find a 5v SB power line on the power connector for the motherboard. On my console, and others I looked at, the orange wires coming off of the PSU are 5v SB. I simply tapped one of the 5v SB lines and a GND line right from the PSU connector port on the motherboard, and backfed one of the 5v and GND GPIOs on the pi. When I plug the console in, the pi is powered and boots up.

Next I will need a way to turn the console on and off. I was hoping to just tap into the I2C bus on the console, which would allow me to not only control power cycling, but control things like reading/writing the EEPROM, change LED colors, control fan speed, etc. Unfortunately I was unable to find any information on where the pins for it are, so I reluctantly tapped the power button pin on the switchboard on the front of the console.

Once I had the wire soldered in and connected to pin #12 on the pi, I wrote a quick python script to pulse the pin:

Code: Select all

#!/usr/bin/python

import RPi.GPIO as GPIO
import time

# Set the numbering system to the pin numbers and not the SoC numbers.
GPIO.setmode(GPIO.BOARD)

# Set pin 12 as an output gpio.
GPIO.setup(12, GPIO.OUT)

# Pull pin 12 low for 1 second to cycle power on the console.
GPIO.output(12, 0)
time.sleep(0.1)
GPIO.output(12, 1)
Once I SSH into the pi I can easily turn the console on or off by running this script (XboxPower.py). Awesome, now I just need to tap the D0 line and... shit, this console is a v1.6... Unfortunately I had a v1.6 console in front of me, which means I have to manually rebuild the LPC port to make the connections live again. No problem, I have some 30 AWG wire laying around so it only took a few minutes to do.
Full Size
Image

Now that I have the D0 line tapped and the LPC port is fully functional again, it's time to give things a test. If I SSH into my pi and run my boot script the console powers on, run it again and the console powers off. If I ground the D0 line the console frags at boot, which is good. This means the console is trying to load the BIOS image from the LPC port, and because no image is loaded, the console can't boot and instead frags. Sweet, now the preparations are complete, on to step two!
Full Size
Image

Step 2 - Emulate the LPC Port
Coming soon...
Don't snort the magic, we need it for the network.
User avatar
XZodia
Staff
Posts: 2208
Joined: Sun Dec 09, 2007 2:09 pm
Location: UK
Contact:

Re: X-Pi, an xbox modchip using a Raspberry Pi

Post by XZodia »

Cool stuff =)
Image
JacksonCougar wrote:I find you usually have great ideas.
JacksonCougar wrote:Ah fuck. Why must you always be right? Why.
User avatar
Grimdoomer
Admin
Posts: 1835
Joined: Sun Dec 09, 2007 9:09 pm

Re: X-Pi, an xbox modchip using a Raspberry Pi

Post by Grimdoomer »

I managed to find the I2C pins for the console, they are pins 14 (SDA) and 13(SCL) on the LPC port:
Image

While playing around with the I2C bus trying to find the address for the PIC (small micro controller that controls LEDs, fan speed, power cycling, etc) I managed to accidentally write some data to my consoles EEPROM *whoops*. This made my console halt at startup and flash a red light. Looking at the commands I had just sent to the EEPROM, it looked like I only wrote one byte, 0x0F, at address 0x08. This happens to be the salt for the HMAC SHA1 encryption key used to decrypt the EEPROM, makes sense why the console wont boot. Bad encryption key = invalid EEPROM data.

If I had taken my time I would have realized that the real I2C addresses for the devices on the I2C bus are just the addresses the SMC uses shifted to the right by 1 bit. Oh well, lesson learned...

Code: Select all

SMBDEV_PIC16L = 0x20 -> 0x10
SMBDEV_VIDEO_ENCODER = 0x8a -> 0x45
SMBDEV_TEMP_MONITOR = 0x98 -> 0x4C
SMBDEV_EEPROM = 0xA8 -> 0x54
I quickly wrote a python script using the now know address of the EEPROM to dump it to the ssh console. After putting it into a bin file and opening it in a hex editor I found this, looks like we found my boo-boo!
Image

Since I didn't have a backup of this EEPROM, and there was only 1 byte that was incorrect, I decided to play the guessing game until I found the right value to make the console boot again. I wrote another python script that would turn the console on, loop from 0 to 255, write the current "guess" to the EEPROM, power cycle the console, and check to see if it booted correctly.

Code: Select all

#!/usr/bin/python

import RPi.GPIO as GPIO
from Adafruit_I2C import Adafruit_I2C
import time

# Power pins.
PIN_PWR_SIGNAL = 11
PIN_PWR_CYCLE = 12

# I2C pipe to the eeprom.
xbPic = Adafruit_I2C(0x10)
xbROM = Adafruit_I2C(0x54)

def cyclePower():
    # Pull pin 12 low for 1 second to cycle power on the console.
    GPIO.output(PIN_PWR_CYCLE, 0)
    time.sleep(0.1)
    GPIO.output(PIN_PWR_CYCLE, 1)

def readEEPROM():
    for i in range(16):
        line = [None] * 16
        for x in range(16):
            line[x] = xbROM.readU8((i * 16) + x)

        #print(('0x%02X: ' % (i * 16))
        print(''.join('%02x'% z for z in line))

def readLED():
    return xbPic.readU8(0x08)

# Set the numbering system to the pin numbers and not the SoC numbers.
print('Initializing gpio pins...')
GPIO.setmode(GPIO.BOARD)

# Setup the power pins for the console.
GPIO.setup(PIN_PWR_CYCLE, GPIO.OUT)
GPIO.setup(PIN_PWR_SIGNAL, GPIO.IN, GPIO.PUD_DOWN)

# Check if the console is powered on.
if GPIO.input(PIN_PWR_SIGNAL) == 0:
    print('Xbox is powered off! booting up...')
    cyclePower()
    time.sleep(5)

# Loop through each possible value of a byte.
for i in range(256):
    # Write the new eemprom byte to the console.
    print('trying byte: 0x%02x...' % i)
    xbROM.write8(0x08, i)
    time.sleep(2)

    # Power cycle the console.
    xbPic.write8(0x02, 0x40)

    # Wait for the console to boot and check the led color.
    time.sleep(5)
    if xbPic.readU8(0x08) != 0xFF:
        print('EEMPROM fixed with byte: 0x%02X' % i)
        cyclePower()
        break;

# Cleanup the GPIO resources.
GPIO.cleanup()
Good thing I was watching it as it ran, because there is flaw in this logic. It assumes you can read the LED status register to determine if the console failed to boot (flashing red), or booted correctly (solid green). As I came to find out when I saw the console boot and the script continue to run, the console will always return 0xFF for the LED status. Nevertheless, I found the missing byte (0x67), and my console now boots again.

Lesson learned. Also, if anyone ever needs I can now give a noob friendly tutorial on how to read and write your EEPROM using only a raspberry pi, and two connections to the xbox motherboard. Now back to breaking shit...
Don't snort the magic, we need it for the network.
User avatar
troymac1ure
Keeper of Entity
Posts: 1282
Joined: Sat Aug 09, 2008 4:16 am
Location: British Columbia, Canada, eh
Contact:

Re: X-Pi, an xbox modchip using a Raspberry Pi

Post by troymac1ure »

Very interesting project. Glad to hear your recovered your EEPROM.
User avatar
Grimdoomer
Admin
Posts: 1835
Joined: Sun Dec 09, 2007 9:09 pm

Re: X-Pi, an xbox modchip using a Raspberry Pi

Post by Grimdoomer »

I got the I2C bus wired up to the pi, and started working on code to feed the console a BIOS file during bootup. I also added a switch so I can switch between the pi modchip and stock BIOS.
Image

However, I quickly realized that the pi with a full linux kernel running is not fast enough to interface with the I2C bus of the xbox. I need to run at 33MHz, but the fastest I can poll the GPIOs on the pi is well below that. If I was bold enough to write a kernel module for the pi I could poll fast enough to do it. I could also try overclocking the pi and see how much faster that will make it.

But for now, I ordered some Xilinx CPLDs and some 1Mbit flash chips, so this project will be on hold for a while. Once I get the last breakout board I need for the xilinx chips I can make my own modchip on a bread board until I feel confident enough to get down and dirty with the pi linux kernel.
Don't snort the magic, we need it for the network.
Zone117x
Posts: 5
Joined: Mon May 09, 2011 10:31 pm

Re: X-Pi, an xbox modchip using a Raspberry Pi

Post by Zone117x »

Great read. Would love to see it finished.
User avatar
neodos
Posts: 1493
Joined: Sun Dec 09, 2007 8:58 pm

Re: X-Pi, an xbox modchip using a Raspberry Pi

Post by neodos »

Very cool stuff! thanks for sharing.
Post Reply