HackMii

Notes from inside your Wii

HackMii header image 2

boot0 / skyeye

June 12th, 2008 by bushing · 8 Comments

(This is a continuation of boot0)

One of the medium-to-long-term projects that Marcan and I have been working is hacking Skyeye to get it to emulate the Starlet.  I don’t think will ever be useful as more than a tool for debugging the lowest-level hacks to boot2 that we plan to attempt, but it’s neat to actually see this code really running.

Skyeye is a generic ARM emulator, and it happens to emulate a lot of devices that we don’t need and can’t use (LCD panels, keyboards, networking, etc…).  So, we’ve been coding drivers for the other parts of the Starlet that we know about — OTP and SEEPROM for keys, NAND flash driver, AES and SHA engines, GPIO ports, debug port … 

At this point, it can either boot a modified version of boot2 (directly from a specially-crafted ELF), or it can boot from a specially-crafted ELF of boot0, its bootrom.  After months of hacking on it, if I give it a real NAND flash dump, boot0 can load and run boot1, and boot1 can load, verify, and run boot2 (which then dies when it tries to load the FS driver due to an MMU problem — we’ll get there eventually).  

Just for fun, here’s what boot0 looks like:

$ ./binary/skyeye -e boot0.elf
arch: arm
mach info: name starlet, mach_init addr 0x44ff0
cpu info: armv5, arm926ejs, 41069260, ff0ffff0, 2
nandflash: dump ./nand.bin
Flash DumpType = 0
file size:553650240
nandflash_lb_poweron
Devicesize = 21000000
Starlet Init
SKYEYE: use arm926ejs mmu ops
MMU init
ELF loading: bigendian 1
ELF section: 0x00001000 0x00001000 0xffff0000 0x00008000
start addr is set to 0xffff0000 by exec file.

(code execution starts here)
[STARLET]: Set memory mirror flags = 00000000
[STARLET]: AES: reset
[STARLET]: AES: key=9258a75264960d82676f904456882a73
[STARLET]: AES: IV=00000000000000000000000000000000
[STARLET]: AES: source addr = 0d400000
[STARLET]: AES: dest addr = 0d400000
[STARLET]: SHA: Init
[STARLET]: SHA: address=0d400000
[NAND] reset
[STARLET]: OTP: Initializing...
[STARLET]: OTP: Successfully read data from file for NG ID 0416b6cc
[STARLET]: UNIMPLEMENTED: starlet_hollywood_write(addr:0x0d8000dc, data:0x00ff0000)
[STARLET]: GPIO1 direction update: 00000000 -> 00ff0000
[STARLET]: DEBUG[80]
[NAND] READ1 page 000000 to d400000,d417800
[STARLET]: DEBUG[01]
[STARLET]: DEBUG[81]
[NAND] READ1 page 000001 to d400800,d417880
[STARLET]: AES: src_ptr=0d400000, iv_reset=1, num_bytes=2048
[STARLET]: DEBUG[02]
[STARLET]: DEBUG[82]
[NAND] READ1 page 000002 to d401000,d417800
[STARLET]: AES: src_ptr=0d400800, iv_reset=0, num_bytes=2048
[STARLET]: SHA: Update(d400000, 800)
[STARLET]: DEBUG[03]
[STARLET]: DEBUG[83]
[NAND] READ1 page 000003 to d401800,d417880
[STARLET]: AES: src_ptr=0d401000, iv_reset=0, num_bytes=2048
[STARLET]: SHA: Update(d400800, 800)
[STARLET]: DEBUG[04]
[STARLET]: DEBUG[84]
[NAND] READ1 page 000004 to d402000,d417800
[STARLET]: AES: src_ptr=0d401800, iv_reset=0, num_bytes=2048
[STARLET]: SHA: Update(d401000, 800)
[STARLET]: DEBUG[05]
[STARLET]: DEBUG[85]
[NAND] READ1 page 000005 to d402800,d417880
[STARLET]: AES: src_ptr=0d402000, iv_reset=0, num_bytes=2048
[STARLET]: SHA: Update(d401800, 800)
[STARLET]: DEBUG[06]
[STARLET]: DEBUG[86]
[NAND] READ1 page 000006 to d403000,d417800
[STARLET]: AES: src_ptr=0d402800, iv_reset=0, num_bytes=2048
[STARLET]: SHA: Update(d402000, 800)
[STARLET]: DEBUG[07]
[STARLET]: DEBUG[87]
[NAND] READ1 page 000007 to d403800,d417880
[STARLET]: AES: src_ptr=0d403000, iv_reset=0, num_bytes=2048
[STARLET]: SHA: Update(d402800, 800)
[STARLET]: DEBUG[08]
[STARLET]: DEBUG[88]
[NAND] READ1 page 000008 to d404000,d417800
[STARLET]: AES: src_ptr=0d403800, iv_reset=0, num_bytes=2048
[STARLET]: SHA: Update(d403000, 800)
[STARLET]: DEBUG[09]
[STARLET]: DEBUG[89]
[NAND] READ1 page 000009 to d404800,d417880
[STARLET]: AES: src_ptr=0d404000, iv_reset=0, num_bytes=2048
[STARLET]: SHA: Update(d403800, 800)
[STARLET]: DEBUG[0a]
[STARLET]: DEBUG[8a]
[NAND] READ1 page 00000a to d405000,d417800
[STARLET]: AES: src_ptr=0d404800, iv_reset=0, num_bytes=2048
[STARLET]: SHA: Update(d404000, 800)
[STARLET]: DEBUG[0b]
[STARLET]: DEBUG[8b]
[NAND] READ1 page 00000b to d405800,d417880
[STARLET]: AES: src_ptr=0d405000, iv_reset=0, num_bytes=2048
[STARLET]: SHA: Update(d404800, 800)
[STARLET]: DEBUG[0c]
[STARLET]: DEBUG[8c]
[NAND] READ1 page 00000c to d406000,d417800
[STARLET]: AES: src_ptr=0d405800, iv_reset=0, num_bytes=2048
[STARLET]: SHA: Update(d405000, 800)
[STARLET]: DEBUG[0d]
[STARLET]: DEBUG[8d]
[NAND] READ1 page 00000d to d406800,d417880
[STARLET]: AES: src_ptr=0d406000, iv_reset=0, num_bytes=2048
[STARLET]: SHA: Update(d405800, 800)
[STARLET]: DEBUG[0e]
[STARLET]: DEBUG[8e]
[NAND] READ1 page 00000e to d407000,d417800
[STARLET]: AES: src_ptr=0d406800, iv_reset=0, num_bytes=2048
[STARLET]: SHA: Update(d406000, 800)
[STARLET]: DEBUG[0f]
[STARLET]: DEBUG[8f]
[NAND] READ1 page 00000f to d407800,d417880
[STARLET]: AES: src_ptr=0d407000, iv_reset=0, num_bytes=2048
[STARLET]: SHA: Update(d406800, 800)
[STARLET]: DEBUG[10]
[STARLET]: DEBUG[90]
[NAND] READ1 page 000010 to d408000,d417800
[STARLET]: AES: src_ptr=0d407800, iv_reset=0, num_bytes=2048
[STARLET]: SHA: Update(d407000, 800)
[STARLET]: DEBUG[11]
[STARLET]: DEBUG[91]
[NAND] READ1 page 000011 to d408800,d417880
[STARLET]: AES: src_ptr=0d408000, iv_reset=0, num_bytes=2048
[STARLET]: SHA: Update(d407800, 800)
[STARLET]: DEBUG[12]
[STARLET]: DEBUG[92]
[NAND] READ1 page 000012 to d409000,d417800
[STARLET]: AES: src_ptr=0d408800, iv_reset=0, num_bytes=2048
[STARLET]: SHA: Update(d408000, 800)
[STARLET]: DEBUG[13]
[STARLET]: DEBUG[93]
[...]

[STARLET]: DEBUG[2d]
[STARLET]: DEBUG[ad]
[NAND] READ1 page 00002d to d416800,d417880
[STARLET]: AES: src_ptr=0d416000, iv_reset=0, num_bytes=2048
[STARLET]: SHA: Update(d415800, 800)
[STARLET]: DEBUG[2e]
[STARLET]: DEBUG[ae]
[NAND] READ1 page 00002e to d417000,d417800
[STARLET]: AES: src_ptr=0d416800, iv_reset=0, num_bytes=2048
[STARLET]: SHA: Update(d416000, 800)
[STARLET]: DEBUG[2f]
[STARLET]: DEBUG[af]
[STARLET]: AES: src_ptr=0d417000, iv_reset=0, num_bytes=2048
[STARLET]: SHA: Update(d416800, 800)
[STARLET]: DEBUG[30]
[STARLET]: DEBUG[b0]
[STARLET]: SHA: Update(d417000, 800)
[STARLET]: SHA: Finalizing
[STARLET]: DEBUG[0a]
[STARLET]: DEBUG[88]
RD MMU 0x1: 00052078
[STARLET]: ========= NOW RUNNING IN BOOT1 CONTEXT =========
The “DEBUG[xx]” output indicates which flash page it’s currently reading (with the 0x80 bit as a strobe), and if boot1 verifies, it outputs “0a / 88” and then jumps to boot1.

Tags: Wii

8 responses so far ↓

  • 1 zeroZshadow // Jun 12, 2008 at 6:04 am

    Nice progress bushing, keep it up 🙂 i love reading these articles

  • 2 emrikol // Jun 12, 2008 at 6:27 am

    Once again, you are all amazing! I just wish there was some way I could help your endeavor.

    Thanks for being the smart ones! 🙂

  • 3 Crinz // Jun 12, 2008 at 10:32 am

    Is this just to further your understanding of the Wii or do you have any practical application in mind with the use of this?

    unless you want to keep things close to your chest (for obvious reasons)

  • 4 superdave // Jun 12, 2008 at 10:23 pm

    Not half bad! How complex is the Starlet’s MMU? I’ve seen ones that run the gamut with ARMs; I once worked with one particular chip where the vendor actually told us to just not use the MMU (it was their own hastily handcrafted IP), so I hope it’s not quite as buggy as that. 🙂

  • 5 SquidMan // Jun 12, 2008 at 10:53 pm

    Very nice work you guys! You are all just so amazing and work so hard and ask for nothing.
    Also, would that key that is set for the AES be boot1’s key? I bet it is! 😛

  • 6 bushing // Jun 13, 2008 at 3:54 am

    @Crinz: This is just to further our understanding, yes. While you could use this as a piece of a Wii emulator, it would silly — there are far easier ways to emulate IOS.

    However, I *do* believe that we will be able to use this to “further our understanding” enough to eventually do boot2 patching.

    @superdave: Well, that’s part of the problem. We don’t actually know exactly what kind of MMU it is. Segher believes the chip is an ARM926-derivative, based on code inspection. I now think it’s an NEC ARM SoC, and based on their offerings it might be an ARM946 (which Skyeye doesn’t even support, but we could add support in…)

    I tried injecting some code into my Wii to read the Chip ID register, and got “00010000” out of it, so … that wasn’t much help. I can post a disassembly of the MMU-related functions, if you think they’d help to understand what’s going on.

    @SquidMan: Yup. 🙂 I’ll post a bit more about that in my next post (about boot1).

  • 7 superdave // Jun 13, 2008 at 7:58 am

    @bushing: Well, the difference between a 926 and 946 is generally in your favor, since you get rid of the Jazelle unit and dumb down the MMU to an MPU (and I wouldn’t lean towards the Wii having a 926, since that only comes in the EJ-S flavor and I can’t see Nintendo using the Jazelle stuff for an I/O processor). I would actually say that the 946 makes a whole lot more sense for what the Starlet is doing, since the entire Wii makes rather sparse use of VM as a whole.

    If you wanna post or email me the asm (or even the binary, since I have IDA Pro), it might be fun to look at, but I’m pretty short on time these days (and having just waded through most of the System Menu looking for something, I’m in need of a bit of a break; hopefully IDA Pro’s ARM facilities are better than the PPC ones).

  • 8 WiiGator // Jul 29, 2008 at 3:04 pm

    Hello Bushing,

    can you provide the source code for the drivers (e.g. as patch for Skyeye)?

You must log in to post a comment.