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

Maxternal

Peanut Gallery Spokesman
OP
Member
Joined
Nov 15, 2011
Messages
5,210
Trophies
0
Age
40
Location
Deep in GBAtemp addiction
Website
gbadev.googlecode.com
XP
1,709
Country
First off, for anyone who wants to download our teaser release, miscellaneous tools or just look at the code, the GoogleCode page can be found here : https://code.google.com/p/gbadev/

. . .

The title is what I hoped this thread will EVENTUALLY become
(although now I realize it, at best, will become a place to post 3-core Linux development updates and, maybe, eventually, a 3-core library of sorts to try to add minimal ASMP 3-core support to libogc homebrew)

I just thought I'd make a place where everyone who knows anything about this can contribute and compare notes with discoveries, code spinets, further detail on the process, etc.




I'll start with what little I've found / come up with so far (Haven't found TOO much time between different day to day activities so if it seems too limited, don't complain about it, just add to it :) )


First is Marcan's blog entry.
http://fail0verflow.com/blog/2013/espresso.html
Here's a summary of the process as I understood it
  1. Load your app into memory. It either needs to be loaded into memory areas that won't be overwritten with 1-200 when it's loaded and running or be prepared to load the rest of it later from a drive or NAND.
  2. The 1-200 title needs to be loaded into memory (1-200 that Marcan mentioned in the blog is a name based off hex values. This might be more commonly recognized as 1-512 or, more incorrectly, IOS512)
  3. Starting from PPC, work some magic to load some ARM code into memory and get it running.
  4. wait for and replace the right instruction with a link to your PPC code (this should already be in memory before or as part of step 3 since I'm not sure if you'll have time to load it at once 1-200 has started doing it's thing.)
  5. The PPC binary loaded at this point can either be the Linux kernel or you're traditional homebrew app. Either way, one of the first things it needs to do is init the cores
#1, #2 : loading 1-512 into memory

Since Mini didn't really have NAND file system support and we didn't really want to write that support into it, the above code also includes code to preload the 1-512 title into memory from the PPC side before running the ARM code. We were lucky that none of the memory addresses clashed so our Linux kernel, the 1-512 title AND the nSwitch code can all coexist at once in memory. To get access to this, we used AHBPROT access and patched out NAND access. (see code from #3 below)

#3 : getting custom ARM code running to reset and watch PPC

We used Mini as a base for ARM code and nSwitch as a base to get it running since it was already loading a version of Mini into memory and running it.
Here's that code :
https://code.google.com/p/gbadev/source/browse/nswitch/source/main.c
Since the HackMii installer for Wii U doesn't install the BootMii IOS (which nSwitch depends on) We also included a WAD for that IOS in our repository. Crediar was also nice enough to hand us some code that could be used to load Mini WITHOUT using the BootMii IOS ... but since the IOS's built-in method of reloading an IOS (such as the BootMii IOS) shuts everything down nicely to make it ready for the new IOS being loaded ... with this new code WE had to do that part. We've only recently figured out how to do that and it now works fine for the v2.6 Linux Kernel (previously, it would get stuck when we used that loading method because it couldn't get access to Bluetooth or USB. The latter was needed for a keyboard and mouse to login with.) The v3.X Linux kernels, though, do NOT work with this loading method yet so we still have both code options in there.

#4 : the actual race attack

most of the code for that is to be found here ... as well as a lot of garbage I need to get rid of
https://code.google.com/p/gbadev/source/browse/armboot/powerpc_elf.c

#5 : Initializing the new cores

I tried taking the pseudo-C code he had down there and converting it into Assembly like it should be. I don't have a lot of experience with assembly so it's obviously not complete (and may not have good syntax) but it's what I've got.
- I put parenthesis after the SPR register numbers in his original code and then commented them out when replacing them with ASM.

<original assembly moved to googlecode page. See link below>

https://code.google.com/p/gbadev/source/browse/armboot/stubsb1/stub_sb_on.s
This is on our GoogleCode page. I basically copied and pasted the assembly from here into that and then went through and figured out which lines I had to remove to make Linux not crash on me.

(They're still there, just commented out or bypassed.)
The
bcr |= 0x08000000;
in the global init and the
if(pvr & 0xFFFF == 0x101)
section had Linux getting stuck while the Linux kernel started up (and I can't remember if there was something else, too)

and while with a few variations to make Linux run on core1 or core2 DID execute, their state coming out of a fresh reset (unlike core0 that comes out of the bootROM execution) also made them get stuck in the middle of the Linux kernel startup process.
Also, in the above code, I mostly assumed on my first tests that Linux would already contain a lot of the "standard, boring init" sequences mentioned by Marcan so I left that out. It was good enough to get things running for now but all this code will eventually have to be unified to make sure everything is REALLY happening as it should



- - - - - - - - - - - - - - - - - - - - - - - - -




Alternate course of action
My original idea was to just make a library that could be compiled into an app (creating a single DOL for each app that could be run from HBC) and be used to unlock and kickstart the extra cores and provide a simple means to run code on them. The problem with this is that we would need to get the IOS back in place in order to run any liboGC code. Without Boot2, Mini finds that difficult so we would need to patch the unlocking code into the IOS. THIS poses a problem because that process needs to invalidate the ARM cache which can only be done, to my knowledge, from the kernel and the kernel code for the IOS is in a memory location that PPC just CAN'T access even with AHBPROT disabled.

This doesn't mean it's impossible ... it's just complicated.

additional note : I was looking through this page http://wiibrew.org/wiki/IOS/Syscalls and it looks like syscalls 0x3F and 0x40 are to invalidate and flush the cache respectively. This is EXACTLY what I was looking for to be able to patch the race attack into the IOS. libogc number crunching here we come!!! (just as soon as I brush up a bit on my ARM assembly :P )

Yet another note: while the syscalls to flush/invalidate the cache work just fine, it looks like the ones to reset PPC don't return until much after PPC has already finished running the bootROM (at which point it's too late for the race attack) so that means I'd either need to perform the race attack and the PPC reset in separate processes (assuming the ARM kernel doesn't just stop all userland processes while it's running) or patch the race attack into the IOS kernel itself. Now, the IOS kernel can't be edited from userland so we'd need to load a new kernel from NAND, pre-patch it and then get it to load reload into it. The thing here is that getting it to manually reload an IOS like that would make it a lot easier to just temporarily load MINI to do the race attack with the new IOS preloaded into memory and have MINI exit to the new IOS kernel when it's done. I've only made a couple of attempts at this but they've failed so that's where my next step lies.

Current course of action
What we're currently doing is taking advantage of the ELF loader built into the mini to make a kind of ELF forwarder DOL that unlocks and inits the cores with 1-200 and then run a second ELF file. I'll try to pack it up and post a link when I can but the code can be found at http://gbadev.googlecode.com/


Links that might help


Datasheets
http://www.raidenii.net/files/datasheets/cpu/ppc_750cl.pdf
https://www-01.ibm.com/chips/techli...9B20050FF778525699600719DF2/$file/6xx_pem.pdf

assembly tutorials and references
http://www.freescale.com/files/32bit/doc/app_note/AN1809.pdf
a nice, basic, little tutorial on PowerPC assembly at WiiBrew : http://wiibrew.org/wiki/Assembler_Tutorial
and another one from IBM http://www.ibm.com/developerworks/linux/library/l-powarch/
aaand another one http://gchiesa.smos.org/pub/_documentation/ISA_PPC/


SMP and Linux code
http://lxr.free-electrons.com/source/arch/powerpc/kernel/smp.c?v=3.6;a=powerpc
http://www.tldp.org/HOWTO/pdf/SMP-HOWTO.pdf
https://launchpad.net/ubuntu/precise/ package/linux-image-3.2.0-23-powerpc-smp
https://launchpad.net/ubuntu/quantal/ package/linux-image-3.5.0-37-powerpc-smp
https://github.com/DeltaResero/GC-Wii-Linux-Kernel-Archive
https://github.com/DeltaResero/GC-Wii-Linux-Kernel-3.4.y
https://github.com/DeltaResero/GC-Wii-Linux-Kernel-2.6.32.y
https://github.com/DeltaResero/GC-Wii-Linux-Kernel-2.6.34.y-POC
https://github.com/DeltaResero/GC-Wii-Linux-Kernel-3.6.11-POC
https://github.com/DeltaResero/GC-Wii-Linux-Kernel-3.0.y
https://github.com/DeltaResero/GC-Wii-Linux-Kernel-3.10.y
https://github.com/DeltaResero/GC-Wii-xf86-video-cube
http://wiibrew.org/wiki/Linux
http://wiibrew.org/wiki/WiiToo!
http://www.gc-linux.org/wiki/MINI:KernelPreviewFive
http://forum.wiibrew.org/list.php?29
http://penguinppc.org/
http://gbatemp.net/threads/linux-help-please.347856/

http://forum.wiibrew.org/read.php?29,68339,68339 (Easy Wii Linux)

Thanks to everyone helping me put these pieces together. (in particular, [user]comex[/user], [user]Crewman[/user] and [user]cory1492[/user] so far ... (and of course, Marcan for the blog post and some clarifying posts here) ) (this thank you list REALLY needs to be amplified)

This OP still needs LOTS of updating and cleanup ... on my (rather lengthy) to-do list.
 

comex

Well-Known Member
Newcomer
Joined
Jan 21, 2007
Messages
56
Trophies
0
XP
243
Country
United States
void realEntryPoint()

C is unlikely to work here, because you don't have a stack. Just use a .s file, you already practically wrote the whole thing in assembly (which is, incidentally, unnecessary with asm(), since you can do the math and such in C, edit: and you shouldn't be using explicit registers with asm()).

asm("andi %r3,%r3,0xBFFFFFFF");

This is unlikely to work unless your assembler is magic, because andi is not an instruction and the operand is out of range. rlwinm is the best option if the mask you want is just bit A to bit B, otherwise load the mask into a register.

One of the things I don't get here is what the new_l2cr means. I can't tell if it's a register he didn't provide the number for or just a pseudo-variable he's using for convenience.

just a variable.

Now, after this, since I didn't know what to do with the "standard, boring initialization" parts

just copy libogc's init code.
 

Andy A

Well-Known Member
Newcomer
Joined
Feb 22, 2013
Messages
57
Trophies
0
Age
27
XP
159
Country
Quick question to comex or anyone else who can answer, can messing with these registers cause a possibility to brick the wii U? If not I think I need to get off my arse and get a TV so I can start porting linux (If I ever get the time). Interesting stuff going on finally.
 
  • Like
Reactions: Ray Lewis

Andy A

Well-Known Member
Newcomer
Joined
Feb 22, 2013
Messages
57
Trophies
0
Age
27
XP
159
Country
I think all registers are reset when you turn the console off so there's no permanent changes this would do to the Wii U and nothing that could brick or damage it.
The problem comes when it isn't expecting to run at 3 cores so it may turn the fans down or something like that, you are right in saying that all registers are reset on reboot as that is the nature or registers.
 

Maxternal

Peanut Gallery Spokesman
OP
Member
Joined
Nov 15, 2011
Messages
5,210
Trophies
0
Age
40
Location
Deep in GBAtemp addiction
Website
gbadev.googlecode.com
XP
1,709
Country
The problem comes when it isn't expecting to run at 3 cores so it may turn the fans down or something like that, you are right in saying that all registers are reset on reboot as that is the nature or registers.
Hmm, that's a good point with the fans ... I would guess you might be able to hear the difference if it did but I don't know about that.
 

Crewman

Active Member
Newcomer
Joined
May 9, 2013
Messages
42
Trophies
0
Age
44
XP
142
Country
Gambia, The
if (/*upir(1007) == 0*/ r3) //////////////////////////////////////////////////////{
asm("mfspr %r3,947");
asm("andi %r3,%r3,0xBFFFFFFF");
//scr(947) &= ~0x40000000; // scr, car, and bcr are global SPRs
asm("mtspr 947,%r3");

asm("mfspr %r3,947");
asm("ori %r3,%r3,0x80000000");
//scr(947) |= 0x80000000;
asm("mtspr 947,%r3");

asm("mfspr %r3,948");
asm("ori %r3,%r3,0xfc100000");
//car(948) |= 0xfc100000; // these bit assignments are unknown
asm("mtspr 948,%r3");

asm("mfspr %r3,949");
asm("ori %r3,%r3,0x08000000");
//bcr(949) |= 0x08000000;
asm("mtspr 949,%r3");
}

Try it with:

if (/*upir(1007) == 0*/ r3) //////////////////////////////////////////////////////
cmp 0,r3,0x00
bc 0x04,2,ENDIF

asm("mfspr %r3,947");
asm("andi %r3,%r3,0xBFFFFFFF");
//scr(947) &= ~0x40000000; // scr, car, and bcr are global SPRs
asm("mtspr 947,%r3");

asm("mfspr %r3,947");
asm("ori %r3,%r3,0x80000000");
//scr(947) |= 0x80000000;
asm("mtspr 947,%r3");

asm("mfspr %r3,948");
asm("ori %r3,%r3,0xfc100000");
//car(948) |= 0xfc100000; // these bit assignments are unknown
asm("mtspr 948,%r3");

asm("mfspr %r3,949");
asm("ori %r3,%r3,0x08000000");
//bcr(949) |= 0x08000000;
asm("mtspr 949,%r3");


ENDIF


This could be totally wrong, last time I programmed something in assembly was long time ago.
 
  • Like
Reactions: Maxternal

comex

Well-Known Member
Newcomer
Joined
Jan 21, 2007
Messages
56
Trophies
0
XP
243
Country
United States
I wouldn't worry about bricking unless I was messing with the NAND. Or messing willy-nilly with IOS-U, the way I bricked my first Wii U :(
 

Site & Scene News

Popular threads in this forum

General chit-chat
Help Users
    Veho @ Veho: Thank you based Dinoh.