Hacking Coding vWii 3-core support - everything you need to know.

  • Thread starter Thread starter Maxternal
  • Start date Start date
  • Views Views 242,156
  • Replies Replies 1,263
  • Likes Likes 13
I think it's time to throw up some more Assembly up for discussion again (ARM assembly this time). I finally got around to trying out some of my idea for patching the core enabling race attack into IOS ... BUT the PPC doesn't even get reset.

I haven't really done a WHOLE lot of testing on this but I thought I'd throw it out there in case anyone has any further ideas.



Here's the hex I'm patching into the IOS:
https://code.google.com/p/gbadev/so...=53a5860eee1d5ed922298518649a350838da6161#126

the IOS syscalls (undefined instructions) are based off of this
http://wiibrew.org/wiki/IOS/Syscalls
but I'm not 100% sure if I'm setting the arguments right.

When I run my hex through this disassembler:
http://www.onlinedisassembler.com/odaweb/#view/tab-assembly/offset/00000000
(set to big endian ARMv5te) I get this
Code:
.data:0x00000000    477846c0    ldrbmi r4, [r8, -r0, asr #13]!
.data:0x00000004    e59f005c    ldr r0, [pc, #92] ; 0x00000068
.data:0x00000008    e6000830    ; <UNDEFINED> instruction: 0xe6000830
.data:0x0000000c    e59f0044    ldr r0, [pc, #68] ; 0x00000058
.data:0x00000010    e5902000    ldr r2, [r0]
.data:0x00000014 
.data:0x00000014        loc_00000014:
.data:0x00000014    e59f003c    ldr r0, [pc, #60] ; 0x00000058
.data:0x00000018    e3a01020    mov r1, #32
.data:0x0000001c    e60007f0    ; <UNDEFINED> instruction: 0xe60007f0
.data:0x00000020    e59f0030    ldr r0, [pc, #48] ; 0x00000058
.data:0x00000024    e5903000    ldr r3, [r0]
.data:0x00000028    e1520003    cmp r2, r3
.data:0x0000002c    0afffff8    beq loc_00000014
.data:0x00000030    e59f0020    ldr r0, [pc, #32] ; 0x00000058
.data:0x00000034    e59f1020    ldr r1, [pc, #32] ; 0x0000005c
.data:0x00000038    e5801000    str r1, [r0]
.data:0x0000003c    e59f101c    ldr r1, [pc, #28] ; 0x00000060
.data:0x00000040    e5801004    str r1, [r0, #4]
.data:0x00000044    e59f1018    ldr r1, [pc, #24] ; 0x00000064
.data:0x00000048    e5801008    str r1, [r0, #8]
.data:0x0000004c    e3a01020    mov r1, #32
.data:0x00000050    e6000810    ; <UNDEFINED> instruction: 0xe6000810
.data:0x00000054    e12fff1e    bx lr
.data:0x00000058    01330100    teqeq r3, r0, lsl #2
.data:0x0000005c    38802000    stmcc r0, {sp}
.data:0x00000060    7c800124    stfvcs f0, [r0], {36} ; 0x24
.data:0x00000064    48001802    stmdami r0, {r1, fp, ip}
.data:0x00000068    00000000    andeq r0, r0, r0

Edit : I see a typo on the last memory patching address ... that might be it. I'll have to test.
 
Max, scraped the bucket for people. Shadow said he had the goods, from elite sources, blatax and others seemed like they had skills, testers, ninja and others on linux. That was always the toughest part we figured; smp part, using all three processors. You can spin them up last I heard. Maybe megazig, bubba if he is around, Crediar if he gets his work done (see Twitter), Marcan, others they know can help. Just could not find actual experts.

Going by your posts. Who knows about behind-the-scenes except you and others involved. Good effort, long run, hope you succeed.
 
I think it's time to throw up some more Assembly up for discussion again (ARM assembly this time). I finally got around to trying out some of my idea for patching the core enabling race attack into IOS ... BUT the PPC doesn't even get reset.

I haven't really done a WHOLE lot of testing on this but I thought I'd throw it out there in case anyone has any further ideas.



Here's the hex I'm patching into the IOS:
https://code.google.com/p/gbadev/so...=53a5860eee1d5ed922298518649a350838da6161#126

the IOS syscalls (undefined instructions) are based off of this
http://wiibrew.org/wiki/IOS/Syscalls
but I'm not 100% sure if I'm setting the arguments right.

When I run my hex through this disassembler:
http://www.onlinedisassembler.com/odaweb/#view/tab-assembly/offset/00000000
(set to big endian ARMv5te) I get this
Code:
.data:0x00000000    477846c0    ldrbmi r4, [r8, -r0, asr #13]!
.data:0x00000004    e59f005c    ldr r0, [pc, #92] ; 0x00000068
.data:0x00000008    e6000830    ; <UNDEFINED> instruction: 0xe6000830
.data:0x0000000c    e59f0044    ldr r0, [pc, #68] ; 0x00000058
.data:0x00000010    e5902000    ldr r2, [r0]
.data:0x00000014
.data:0x00000014        loc_00000014:
.data:0x00000014    e59f003c    ldr r0, [pc, #60] ; 0x00000058
.data:0x00000018    e3a01020    mov r1, #32
.data:0x0000001c    e60007f0    ; <UNDEFINED> instruction: 0xe60007f0
.data:0x00000020    e59f0030    ldr r0, [pc, #48] ; 0x00000058
.data:0x00000024    e5903000    ldr r3, [r0]
.data:0x00000028    e1520003    cmp r2, r3
.data:0x0000002c    0afffff8    beq loc_00000014
.data:0x00000030    e59f0020    ldr r0, [pc, #32] ; 0x00000058
.data:0x00000034    e59f1020    ldr r1, [pc, #32] ; 0x0000005c
.data:0x00000038    e5801000    str r1, [r0]
.data:0x0000003c    e59f101c    ldr r1, [pc, #28] ; 0x00000060
.data:0x00000040    e5801004    str r1, [r0, #4]
.data:0x00000044    e59f1018    ldr r1, [pc, #24] ; 0x00000064
.data:0x00000048    e5801008    str r1, [r0, #8]
.data:0x0000004c    e3a01020    mov r1, #32
.data:0x00000050    e6000810    ; <UNDEFINED> instruction: 0xe6000810
.data:0x00000054    e12fff1e    bx lr
.data:0x00000058    01330100    teqeq r3, r0, lsl #2
.data:0x0000005c    38802000    stmcc r0, {sp}
.data:0x00000060    7c800124    stfvcs f0, [r0], {36} ; 0x24
.data:0x00000064    48001802    stmdami r0, {r1, fp, ip}
.data:0x00000068    00000000    andeq r0, r0, r0
Edit : I see a typo on the last memory patching address ... that might be it. I'll have to test.

Maxternal, you might want to edit your post to include a link to the new version or the differences between the 2 versions.
Keep up good work.

btw, I understand the syscalls:
.data:0x0000001c e60007f0 ; <UNDEFINED> instruction: 0xe60007f0
3f void sync_before_read(void *address, u32 size) Invalidates dcache, and something (probably related to flushing memory)
.global sync_before_read
sync_before_read:
.long 0xe60007f0
bx lr

.data:0x00000050 e6000810 ; <UNDEFINED> instruction: 0xe6000810
40 void sync_after_write(const void *address, u32 size) Flushes dcache and does magic bullshit (aka magic AHB operations)
.global sync_after_write
sync_after_write:
.long 0xe6000810
bx lr
I'm assuming that syscall_41 is a call to ppc_boot, am I correct?

.data:0x00000008 e6000830 ; <UNDEFINED> instruction: 0xe6000830
41 ppc_boot(const char *path) Loads a .dol or .elf file into memory and bootstraps the PPC
.global syscall_41
syscall_41:
.long 0xe6000830
bx lr
 
Maxternal, you might want to edit your post to include a link to the new version or the differences between the 2 versions. Keep up good work.
Thanks, good idea. I'll have to do that.
btw, I understand the syscalls: /snip/
I'm assuming that syscall_41 is a call to ppc_boot, am I correct?
/snip/
Yes, it is. (That's what I'm going for at least.) This is STILL untested, though.
I'll let you guys know when that happens and how things went. ;)
 
  • Like
Reactions: Ray Lewis
ok, that didn't work (and I have no idea why)
I think my next attempt will be to just write the ASM equivalent of this
Code:
clear32(HW_RESETS, 0x30);
udelay(100);
set32(HW_RESETS, 0x20);
udelay(100);
set32(HW_RESETS, 0x10);
which is what we use in Mini to reset PPC

and I've written up a pseudo-code idea of how to implement it here http://pastie.org/8444325 that I'm currently converting to assembly and then to hex (mostly just missing the OR command's hex so far)

The thing is that using this to replace that first syscall DOUBLES the size of the ASM code to patch into the IOS (not to mention that I'd also have to preload the 1-512 nandloader into memory myself) so it would be NICE if the syscall would work for me and do it all for me.
 
  • Like
Reactions: Ray Lewis
Isn't the pc register containing the next address to execute?

ok to answer my own question:
ARM Compiler toolchain Using the Assembler Version 4.1
Home > Overview of the ARM Architecture > Program Counter

Program Counter
The Program Counter (PC) is accessed as PC (or R15). It is incremented by the size of the instruction executed (which is always four bytes in ARM state). Branch instructions load the destination address into PC. You can also load the PC directly using data operation instructions. For example, to branch to the address in a general purpose register, use:
MOV PC,R0

During execution, PC does not contain the address of the currently executing instruction. The address of the currently executing instruction is typically PC-8 for ARM, or PC-4 for Thumb.


So in the code below(and the rest of the code not listed but very similar):

.data:0x00000004 e59f005c ldr r0, [pc, #92] ; 0x00000068
.data:0x00000008 e6000830 ; <UNDEFINED> instruction: 0xe6000830
.data:0x0000000c e59f0044 ldr r0, [pc, #68] ; 0x00000058
.data:0x00000010 e5902000 ldr r2, [r0]

the 1st pc should be pointing at 0x00000008 and 0x005c is added to it so it's loading r0 0x00000064?
the 2nd pc should be pointing at 0x00000010 and 0x0044 is added to it so it's loading r0 0x00000054?
 
ok I guess what I've been trying to ask less than artfully is:
How do you know that the syscall to the ppc_boot hasn't changed the pc register in this instruction:
.data:0x00000004 e59f005c ldr r0, [pc, #92] ; 0x00000068

to an address inside the ppc_boot syscall?

Can you add a nop (no operation) instruction or something else in between and then correct whatever other problems may have occurred because of the additional instruction?
.data:0x00000004 e59f005c ldr r0, [pc, #92] ; 0x00000068
.data:0x00000008
.data:0x0000000C e6000830 ; <UNDEFINED> instruction: 0xe6000830
 
So in the code below(and the rest of the code not listed but very similar):

.data:0x00000004 e59f005c ldr r0, [pc, #92] ; 0x00000068
.data:0x00000008 e6000830 ; <UNDEFINED> instruction: 0xe6000830
.data:0x0000000c e59f0044 ldr r0, [pc, #68] ; 0x00000058
.data:0x00000010 e5902000 ldr r2, [r0]

the 1st pc should be pointing at 0x00000008 and 0x005c is added to it so it's loading r0 0x00000064?
the 2nd pc should be pointing at 0x00000010 and 0x0044 is added to it so it's loading r0 0x00000054?
I'm glad I'm not the only one.
I, too, was somewhat perplexed at how my calculations on all my PC relative loads were 4 bytes before what they should be ... but I just assumed that the disassembler comment "; 0x00000068" at the end of each of those lines when I checked my hex was telling me otherwise so I kinda blindly just adjusted them all, trusting in that comment.
During execution, PC does not contain the address of the currently executing instruction. The address of the currently executing instruction is typically PC-8 for ARM, or PC-4 for Thumb.
This, though, does seem to confirm what the disassembler says. It does seem odd, though since to me having the current instruction at PC-8 would mean it's TWO instructions behind and not one.
BOTH your suggestions are worth a try. Let's see what happens.

EDIT : tested and that wasn't it. still need to figure out what's wrong here.
 
  • Like
Reactions: Ray Lewis
ok, here's the other, longer, attempt at doing it without the first syscall
(which doesn't work either)
Code:
.data:0x00000000    477846c0    ldrbmi r4, [r8, -r0, asr #13]!
.data:0x00000004    e59f00a0    ldr r0, [pc, #160] ; 0x000000ac
.data:0x00000008    e5903000    ldr r3, [r0]
.data:0x0000000c    e59f00ac    ldr r0, [pc, #172] ; 0x000000c0
.data:0x00000010    e5901000    ldr r1, [r0]
.data:0x00000014    e3c11030    bic r1, r1, #48 ; 0x30
.data:0x00000018    e5801000    str r1, [r0]
.data:0x0000001c    e59f2098    ldr r2, [pc, #152] ; 0x000000bc
.data:0x00000020    e5921000    ldr r1, [r2]
.data:0x00000024    e28110be    add r1, r1, #190 ; 0xbe
.data:0x00000028        
.data:0x00000028        loc_00000028:
.data:0x00000028    e5920000    ldr r0, [r2]
.data:0x0000002c    e1510000    cmp r1, r0
.data:0x00000030    cafffffc    bgt loc_00000028
.data:0x00000034    e59f0084    ldr r0, [pc, #132] ; 0x000000c0
.data:0x00000038    e5901000    ldr r1, [r0]
.data:0x0000003c    e3811020    orr r1, r1, #32
.data:0x00000040    e5801000    str r1, [r0]
.data:0x00000044    e5921000    ldr r1, [r2]
.data:0x00000048    e28110be    add r1, r1, #190 ; 0xbe
.data:0x0000004c        
.data:0x0000004c        loc_0000004c:
.data:0x0000004c    e5920000    ldr r0, [r2]
.data:0x00000050    e1510000    cmp r1, r0
.data:0x00000054    cafffffc    bgt loc_0000004c
.data:0x00000058    e59f0060    ldr r0, [pc, #96] ; 0x000000c0
.data:0x0000005c    e5901000    ldr r1, [r0]
.data:0x00000060    e3811010    orr r1, r1, #16
.data:0x00000064    e5801000    str r1, [r0]
.data:0x00000068        
.data:0x00000068        loc_00000068:
.data:0x00000068    e59f003c    ldr r0, [pc, #60] ; 0x000000ac
.data:0x0000006c    e3a01020    mov r1, #32
.data:0x00000070    e60007f0    ; <UNDEFINED> instruction: 0xe60007f0
.data:0x00000074    e59f0030    ldr r0, [pc, #48] ; 0x000000ac
.data:0x00000078    e5902000    ldr r2, [r0]
.data:0x0000007c    e1520003    cmp r2, r3
.data:0x00000080    0afffff8    beq loc_00000068
.data:0x00000084    e59f0020    ldr r0, [pc, #32] ; 0x000000ac
.data:0x00000088    e59f1020    ldr r1, [pc, #32] ; 0x000000b0
.data:0x0000008c    e5801000    str r1, [r0]
.data:0x00000090    e59f101c    ldr r1, [pc, #28] ; 0x000000b4
.data:0x00000094    e5801004    str r1, [r0, #4]
.data:0x00000098    e59f1018    ldr r1, [pc, #24] ; 0x000000b8
.data:0x0000009c    e5801008    str r1, [r0, #8]
.data:0x000000a0    e3a01020    mov r1, #32
.data:0x000000a4    e6000810    ; <UNDEFINED> instruction: 0xe6000810
.data:0x000000a8    e12fff1e    bx lr
.data:0x000000ac    01330100    teqeq r3, r0, lsl #2
.data:0x000000b0    38802000    stmcc r0, {sp}
.data:0x000000b4    7c800124    stfvcs f0, [r0], {36} ; 0x24
.data:0x000000b8    48000106    stmdami r0, {r1, r2, r8}
.data:0x000000bc    0d800010    stceq 0, cr0, [r0, #64] ; 0x40
.data:0x000000c0    0d800194    stfeqs f0, [r0, #592] ; 0x250
although I haven't tried THIS one with Bug_Checker_'s PC relative fix yet, without taking that into account, my first suspicion is that I might be misunderstanding what the BIC command does.
 
This, though, does seem to confirm what the disassembler says. It does seem odd, though since to me having the current instruction at PC-8 would mean it's TWO instructions behind and not one.

BOTH your suggestions are worth a try. Let's see what happens.

Could that have something to do with a pipeline and by the time you access the PC it's already moved on to yet another instruction?
 
  • Like
Reactions: Ray Lewis
ough I haven't tried THIS one with Bug_Checker_'s PC relative fix yet, without taking that into account, my first suspicion is that I might be misunderstanding what the BIC command does.
it's clear some bits in r1, 0x30 it's a bit mask, if bit set to 1, that this bit is cleared in r1, if bit set to 0, bit in r1 unchanged (for example http://www.heyrick.co.uk/armwiki/BIC)
 
  • Like
Reactions: Ray Lewis
it's clear some bits in r1, 0x30 it's a bit mask, if bit set to 1, that this bit is cleared in r1, if bit set to 0, bit in r1 unchanged (for example http://www.heyrick.co.uk/armwiki/BIC)
Yeah, I've seen BIC when coding MSP430 assembly, and it was the same. On the MSP, it also used BIS (BIt Set) instead of OR. Kinda made me wish there was a built in BIC function in C instead of having to use &= ~
 
  • Like
Reactions: Ray Lewis
it's clear some bits in r1, 0x30 it's a bit mask, if bit set to 1, that this bit is cleared in r1, if bit set to 0, bit in r1 unchanged (for example http://www.heyrick.co.uk/armwiki/BIC)

ok, seems like I was using it right, then (which means it's something else I'm doing wrong, unfortunately)

BTW, very useful sites you guys are referencing here. Good stuff.
 
  • Like
Reactions: mike1 and Ray Lewis
Ok, as a test, I tried patching in really simple code to copy a value from one memory address to another (invalidating and flushing the cache where needed with syscalls) and THAT worked
Code:
.data:0x00000000    477846c0    ldrbmi r4, [r8, -r0, asr #13]!
.data:0x00000004    e59f302c    ldr r3, [pc, #44] ; 0x00000038
.data:0x00000008    e2832020    add r2, r3, #32
.data:0x0000000c     
.data:0x0000000c        loc_0000000c:
.data:0x0000000c    e3a01020    mov r1, #32
.data:0x00000010    e1a00002    mov r0, r2
.data:0x00000014    e60007f0    ; <UNDEFINED> instruction: 0xe60007f0
.data:0x00000018    e5921000    ldr r1, [r2]
.data:0x0000001c    e3510000    cmp r1, #0
.data:0x00000020    012fff1e    bxeq lr
.data:0x00000024    e5831000    str r1, [r3]
.data:0x00000028    e3a01020    mov r1, #32
.data:0x0000002c    e1a00003    mov r0, r3
.data:0x00000030    e6000810    ; <UNDEFINED> instruction: 0xe6000810
.data:0x00000034    eafffff4    b loc_0000000c
.data:0x00000038    01330100    teqeq r3, r0, lsl #2
PHP:
//basically
DCInvalidateCache(0x01330120, 32);
*(u32*)0x01330100 = *(u32*)0x01330120;
DCFlushCache(0x01330100, 32);
so something's just wrong with how I'm using that first ppc_boot() syscall ...
it just passes it right up and gets stuck in the loop afterward ... but PPC keeps running

EDIT :
The things I can think of that I might be doing wrong

1- I'm pointing it a DOL file it doesn't like (I've only tried so far the 00000003.app from 1-512 and the 00000017.app from the latest system menu) The trick would be finding something it DOES like in that case.
2- I'm pointing at an app file and it might want the TMD or just the folder so it can find the right file itself.
3- Somehow the memory address I'm passing to it is getting messed up and is no longer pointing to the path or I'm getting it from the wrong address with the STR command.
4- A combination of the above.

EDIT2 : It's also conceivable that syscalls to run kicstart PPC are not allowed to be run from ES (which is where my patches are)
What MIGHT normally be done is that ES runs the syscall to reload to the IOS of the new title and just leaves arguments behind so that the NEW IOS will know which PPC title to load and run (which could be performed outside of ES)
 
  • Like
Reactions: Ray Lewis
Nice progress here.

I think the whole code is to long to test it at once without debug information.
You could try to toggle an output port of the WIIU(maybe the sensorbar) after each of your instructions. If you monitor the port you can see where the programm stop.
 
  • Like
Reactions: Maxternal
Nice progress here.

I think the whole code is to long to test it at once without debug information.
You could try to toggle an output port of the WIIU(maybe the sensorbar) after each of your instructions. If you monitor the port you can see where the program stop.
Not a bad idea. Easier still since my last test proved that I CAN perform cache flushing and invalidation just fine I could just have it increment a register and write to memory as it goes through the code, with PPC watching that address and printing it out on screen.

I'll have to use something like that to confirm my suspicions, of course, but so far it seems to be getting past the ppc_boot() syscall just fine but it's treating it as a NOP either because it's not permitted in ES or my arguments are invalid (HOPEFULLY the latter)
 
  • Like
Reactions: jammybudga777
this is a great thread with people working hard and whiling to share around info. keep up the great work guys :) its a shame i dont have the brains to participate and help out at all
 
All Maxternal starting it. Took it on and others found out and then came to help. Delta and Ninja (where is Ninja?) were posting Linux "stuff." Been pulling for Maxternal since the beginning.
 
All Maxternal starting it. Took it on and others found out and then came to help. Delta and Ninja (where is Ninja?) were posting Linux "stuff." Been pulling for Maxternal since the beginning.


I've been lurking. Further Linux development hinges on getting the cores spun up. Max & company know where and how to find me if/when they need me.
That and Final Fantasy XIV has a grip on me...
 

Site & Scene News

Popular threads in this forum