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

Scuba156

Well-Known Member
Member
Joined
Jan 19, 2010
Messages
340
Trophies
0
Age
36
XP
344
Country
Then what do you suggest? People to write a new ecosystem from scratch? Is that you volunteering to help?

If new libraries are needed from scratch then yes I would be there to help at the first possible chance.
There's a big difference between including a copyrighted library from a stolen SDK and a library that's a direct result of reverse-engineering.

A library that was made by reverse-engineering (NOT dumping) and written for a given language from the ground up is not stolen code - it was made by the hacker in question even if it's virtually identical to the original SDK. A stolen SDK is just stolen.

In a similar fashion a stolen painting is just a stolen painting wheras a reproduction is a reproduction - one is illegal and one is not.

Contrary to popular belief reverse-engineering is not illegal all around the globe - in may countries (for example mine) by purchasing given hardware you also logically purchase whatever is in the hardware, meaning the firmware. You purchase an almost indispensible right to do whatever you feel like doing with your system, software, hardware and firmware-wise. This includes reverse-engineering and if the result of such activity is a library that does not contain stolen code, merely references to adresses that already exist on the system, it's entirely legal to distribute it.

The specific commands are already on the system in question - all an SDK does is dictating which commands should be used.
I agree with you, I was pointing out more of the fact if things were done with an official SDK or something stolen from it, not from a reverse engineering perspective. Using the Xbox 360 as an example (just as its were my experience is), anything compiled with the official XDK was illegal to distribute as it contained MS code were as libXenon (open SDK) was free from this.

Personally I see reverse engineering more of a moral choice and not a legality.
 
  • Like
Reactions: chartube12

Scuba156

Well-Known Member
Member
Joined
Jan 19, 2010
Messages
340
Trophies
0
Age
36
XP
344
Country
Scuba and Foxi, thanks for the clarification. Lol, I guess if you "Copy/change" the official SDK, then quite possibly that COULD save dev time;-) Unless I am misreading something. Thanks for offering to help with some parts Scuba. This is THE prime example as to why I have been putting this thread out there at every opportunity. We have a chance to get something done, something cool. The more experts and educated we get, the more clarifications we can have and information sharing we can promote. Randomizer, nobody is bickering.

1.) 3 core code running in vWii mode
2.) Linux ported to vWii with 3 code part being developed (correct me Maxternal, or others)
3.) From there, it may be what Scuba offered to help with, and/or possible to go further in and possibly get to Wii U mode. This is my want, but who knows?

Maxternal is currently working, others help, not sure if PM's are sent (hopefully so), and that is THE cornerstone right there. Again, VERY HAPPY to see veterans I've seen around (some on wiibrew) stop by, some from other scenes also (lol, let me know about progress there;-)) If I can ask for help, generate interest (at least this), and get more interested in a challenge that has a good END result for everyone then that is my purpose. Like, hate; even if it is AN interest or curiosity I can generate. Also to test. THis goes for anyone. "Ray, try this, goes on SD card...run, how does it run there?" As long as it is nothing that could brick (pretty much modding an IOS).
I can't help with what Maxternal is currently doing as I have no Assembly knowledge or experience but I have c/c++ experience for when it is needed down the track.
 

Crewman

Active Member
Newcomer
Joined
May 9, 2013
Messages
42
Trophies
0
Age
44
XP
142
Country
Gambia, The
0x1330100 = JUMP_INSTRUCTION;



Branch instruction:
Bits 0-5
010010 ->Opcode for branch instruction(b instruction)
Bits 6-29
Absolute or relative branch address(In our case the start of the code for step #5, which is a absolute address) don't know if the msb is bit6 or bit29(I assume bit6 is msb)
Bit 30
1 ->Absolute address bit -- If this field is set, the instruction is interpreted as an absolute address, otherwise it is interpreted as a relative address
Bit 31
0 -> Link bit -- If this field is set, the instruction sets the link register with the address of the next instruction
This value hast to be loaded into a register and then stored to 0x1330100, which can be done like this:

lis %r3,hi(address in hex)
addi %r3,%r3,lo(address in hex)
slwi %r3,%r3,2
addis %r3,%r3, hi(0x48000002)
addi %r3,%r3,lo(0x48000002)

lis %r4,hi(0x1330100)
addi %r4,%r4,lo(0x1330100)
stw %r3,0(%r4)

or in C:

uint32 ADDRESS=*address in hex*;
ADDRESS<<=2;
ADDRESS+=0x48000002;
uint32 volatile* const RAM= (uint32*)0x1330100;
RAM=ADDRESS;

Could be some errors in it^^ hf
 

JoostinOnline

Certified Crash Test Dummy
Member
Joined
Apr 2, 2011
Messages
11,005
Trophies
1
Location
The Twilight Zone
Website
www.hacksden.com
XP
4,339
Country
United States
Reverse-engineering code is quite a task Joostin, I wouldn't equate it to a simple copy-paste.
No argument there, it's very difficult, but I stand by my statement. Being good at reverse engineering doesn't mean you are good at writing code from scratch. You obviously have to know something about coding if you want to reverse engineer, but you certainly don't have to be skilled to the point where you could write up an entire library from scratch.

Maybe I'm wrong, but I don't think that there is much code to reverse engineer for this project.
 
  • Like
Reactions: rednekcowboy

rednekcowboy

Well-Known Member
Member
Joined
Jan 1, 2013
Messages
242
Trophies
0
Age
46
XP
315
Country
Canada
No argument there, it's very difficult, but I stand by my statement. Being good at reverse engineering doesn't mean you are good at writing code from scratch. You obviously have to know something about coding if you want to reverse engineer, but you certainly don't have to be skilled to the point where you could write up an entire library from scratch.

Maybe I'm wrong, but I don't think that there is much code to reverse engineer for this project.


100% agree. I can alter someone else's code and add and remove stuff but to start from scratch I'd be buggered. Well, I'm starting to get a little more confident, but I'm self-taught so google is most definitely my friend!! LOL
 

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
Preferrably in C, anyone know? ...

1. How to tell how much memory the current IOS is taking up and what the start and end of that memory area is?

2. How to tell the start address of any given function in the IOS?

3. What the entry point of the mini's armboot.bin file is?


The reason I ask is because I would PREFER not to overwrite more than a single address in the IOS in order to get ARM code running, a single address that I could later put back and leave the IOS intact.

I also would like to test my idea by moding nSwitch to load the mini manually without using the bootmii IOS like it currently does (since the bootmii IOS apparently isn't an option on a Wii U). My hope would be to then further mod it into an ELF forwarder that would the load and run the app itself.
 
  • Like
Reactions: Ray Lewis

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
I can't answer your questions, but I do happen to know that you can dump Bootmii as IOS and install it on a vWii. You just can't do it with the HackMii installer.
oh, okay. That's cool. I was just worried that that would be dangerous to do somehow. Could be useful info for testing some stuff. I still see lots of benefits, though, to doing without.
 

JoostinOnline

Certified Crash Test Dummy
Member
Joined
Apr 2, 2011
Messages
11,005
Trophies
1
Location
The Twilight Zone
Website
www.hacksden.com
XP
4,339
Country
United States
oh, okay. That's cool. I was just worried that that would be dangerous to do somehow. Could be useful info for testing some stuff. I still see lots of benefits, though, to doing without.
I don't know why it would be dangerous, as running bootmii doesn't modify the NAND. It's probably easier than modding nswitch though.
 
  • Like
Reactions: Ray Lewis

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
I don't know why it would be dangerous, as running bootmii doesn't modify the NAND. It's probably easier than modding nSwitch though.
Looking at the mini's code, it seems it uses boot2 to reload titles (which is also not present :( ) the main* thing I didn't like about using BootMii IOS is,
(for example)
if someone wanted to add this code to an emulator that was already programmed to interact with a normal IOS and so it goes through all the process of initiating the other cores
BUT
If they come out of that process and the IOS is now gone (along with it's built in IOS reload functionality) and mini ends up being unable to get them their IOS back either, we may have a problem.

Basically, I need to figure out HOW to reload an IOS in vWii while running mini off of the BootMii IOS ... OR figure out how to bypass that part (which is in intriguing concept in and of itself) as not to leave that extra work to the coder who ends up reusing my code.

*and then, of course, there's the fact that dumping the IOS and reinstalling it manually is just extra work for the user OR impossible if they don't have a normal Wii (and then TT throwing a fit if I just pack mine and distribute it. I'm sure HackMii doesn't install it to avoid noobs bricking when doing NAND backups or something like that, too, and I don't want that either.)
 

cory1492

Well-Known Member
Member
Joined
Jun 23, 2005
Messages
1,497
Trophies
1
Location
Home, WhereElse?
XP
335
Country
Canada
or in C:

uint32 ADDRESS=*address in hex*;
ADDRESS<<=2;
ADDRESS+=0x48000002;
uint32 volatile* const RAM= (uint32*)0x1330100;
RAM=ADDRESS;

Could be some errors in it^^ hf

Code:
// assembles a PPC branch or branch with link instruction for hooking
u32 makeBranch(u32 currAddr, u32 destAddr, BOOL linked)
{
    u32 ret = 0x48000000; // range 0-0x1FFFFFC (0x3FFFFFC) (sign extended) negative bit 0x2000000 link bit 0x1
    if(destAddr > currAddr){ // forward branch
        ret = ret | ((destAddr-currAddr)&0x3FFFFFC);
    }
    else{ // backward branch
        ret = (ret | 0x2000000) | ((currAddr-destAddr)&0x3FFFFFC);
    }
    if(linked)
        ret = ret|1;
    return ret;
}
 
...
   // payloadAddr being destination for PPC crt0 that handles all 3 cores, presumably in the self exploiting launching app which will then have 2 separate crt and binaries to juggle
    *(volatile u32*)0x81330100 = makeBranch(0x81330100, payloadAddr, FALSE);
...
or something... (prob never gonna need backward branch) keep in mind branch and branch with link have limited range on PPC, otherwise this function is very reliable :D
 

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
Code:
// assembles a PPC branch or branch with link instruction for hooking
u32 makeBranch(u32 currAddr, u32 destAddr, BOOL linked)
{
    u32 ret = 0x48000000; // range 0-0x1FFFFFC (0x3FFFFFC) (sign extended) negative bit 0x2000000 link bit 0x1
    if(destAddr > currAddr){ // forward branch
        ret = ret | ((destAddr-currAddr)&0x3FFFFFC);
    }
    else{ // backward branch
        ret = (ret | 0x2000000) | ((currAddr-destAddr)&0x3FFFFFC);
    }
    if(linked)
        ret = ret|1;
    return ret;
}
 
...
  // payloadAddr being destination for PPC crt0 that handles all 3 cores, presumably in the self exploiting launching app which will then have 2 separate crt and binaries to juggle
    *(volatile u32*)0x81330100 = makeBranch(0x81330100, payloadAddr, FALSE);
...
or something... (prob never gonna need backward branch) keep in mind branch and branch with link have limited range on PPC, otherwise this function is very reliable :D
Very nice little conversion code there. Takes the work out of pre-calculating and hard coding a value. Makes the code a lot more readable, too.

Just noticed something with the masks you're using there
Code:
01001000000000000000000000000000 = 0x48000000
00000011111111111111111111111100 = 0x3FFFFFC
00000001111111111111111111111100 = 0x1FFFFFC
00000010000000000000000000000000 = 0x2000000
It seems the 0x3FFFFFC mask includes the sign bit anyhow and that would automatically be 1 with a negative number and 0 with a positive number anyhow (as long as they're within range) so I think that could be simplified considerably.

oh, and a backward branch is VERY useful for() a for or while() loop

Also, would you need to shift that 2 bits over (<<2) before OR'ing it in? ... or is it just conveniently taking off those last 2 bits to 32-bit align the address?

Anyway, here's my simplification (correct me if I need to take the bit shift out of there)
PHP:
u32 makeRelativeBranch(u32 currAddr, u32 destAddr, bool linked)
{   s32 destA = (s32)destAddr, currA = (s32)currAddr;
    u32 ret = 0x48000000 | (( destA - currA ) & 0x3FFFFFC );
    if(linked)
        ret |= 1;
    return ret;
}

EDIT: and then another one for an absolute branch.
PHP:
u32 makeAbsoluteBranch(u32 destAddr, bool linked)
{
    u32 ret = 0x48000002 | ( destAddr & 0x3FFFFFC );
    if(linked)
        ret |= 1;
    return ret;
}
The only problem is that an absolute branch can only work within the first 64mb of memory addresses, max (16mb with the bit shift :( ) so I'd have to check again the mem addresses for mem1 and mem2 from the PPC side to see how limiting that would really be.

EDIT 2:another question, is the relative branch relative to the current address or the next one? In other words, if destAddr-currentAddr is zero, would that be en infinite loop or a no-op?
 

chartube12

Captain Chaz 86
Member
Joined
Mar 3, 2010
Messages
3,921
Trophies
1
XP
2,280
Country
United States
Once something user friendly is possible, I would love to test apps for you guys. I know that is a long way off, but so is me buying a wii-u.
 

Crewman

Active Member
Newcomer
Joined
May 9, 2013
Messages
42
Trophies
0
Age
44
XP
142
Country
Gambia, The
1. How to tell how much memory the current IOS is taking up and what the start and end of that memory area is?
I think you don't mean the IOS as it will be possibly be overwritten by the NAND-loader, anyhow the ISO will be automatically reloaded by the NAND-loader.
The Start address of the NAND-loader is defined in it's header, as you know the size of the NAND-loader you can calculate the end address.


2. How to tell the start address of any given function in the IOS?

Don't know why we need the address of an IOS function. But you can get it by revers engineering it.
Anyhow I think you mean the start address of the assembly code executed after CPU reset. I would load the code manually to the RAM, so the start address is the address the code is loaded to.

At least I have a question how you can run ARM code on a PPC? I don't believe that is possible because of the different CPU architectures.

Ps.:
When you only want to overwrite one memory address in RAM use a function-call, like I said earlier.
 
  • Like
Reactions: Ray Lewis

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
I think you don't mean the IOS as it will be possibly be overwritten by the NAND-loader, anyhow the ISO will be automatically reloaded by the NAND-loader.
The Start address of the NAND-loader is defined in it's header, as you know the size of the NAND-loader you can calculate the end address.




Don't know why we need the address of an IOS function. But you can get it by revers engineering it.
Anyhow I think you mean the start address of the assembly code executed after CPU reset. I would load the code manually to the RAM, so the start address is the address the code is loaded to.

At least I have a question how you can run ARM code on a PPC? I don't believe that is possible because of the different CPU architectures.

Ps.:
When you only want to overwrite one memory address in RAM use a function-call, like I said earlier.
What I understood from what marcan said was that the 1-200 title was actually PPC code and what so we needed to be able to run code on "starlet" which is the ARM processor that the IOS run off of. The idea is that if we reset the PPC side, we lose control of it and it automatically boots from some code from a ROM chip that decrypts/validates the 1-200 title in memory so we need the ARM side to wait for the entry point of the 1-200 title to be decrypted so we can overwrite it and get control of it BACK.

overwriting part of the IOS with my own ARM code in order to get control of Starlet temporarily was one of the options I was looking into for that. It's probably the most user friendly, too as my other ideas were creating a separate cIOS based on D2X code or having them dump and install a bootmii IOS.
 
  • Like
Reactions: Ray Lewis

cory1492

Well-Known Member
Member
Joined
Jun 23, 2005
Messages
1,497
Trophies
1
Location
Home, WhereElse?
XP
335
Country
Canada
The bit shift isn't needed... I've been using that hook code on xbox 360 for ages now, and it works as-is (like I said, reliable.) But yeah, they basically re-use the &3 bits for flags in some instructions because of 4 byte alignment for instructions.

notice...
range 0-0x1FFFFFC (0x3FFFFFC sign extended, negative bit 0x2000000) link bit 0x1
It seems the 0x3FFFFFC mask includes the sign bit anyhow and that would automatically be 1 with a negative number and 0 with a positive number anyhow (as long as they're within range) so I think that could be simplified considerably.
A DWORD/u32 is unsigned, subtraction of two u32 when the value being subtracted is greater than the value being subtracted from is by no means guaranteed to give you a value that can just be stuffed into the sign extend mask. Notice the dest/cur are reversed in subtraction of the backwards branch vs. the forward branch, this is to ensure a positive value as a result (instead of using int and a bunch of casting), which gets or'd with the bit that indicates negative/sign extend. To make this function totally safe/complete it really should have a range check before assembling the instruction, but in the case of a bootloader or something, you should know before using it if it will be effective as there are really no feed back mechanisms other than <crash><unplug from wall>. You know though, every time I look at this I have to wonder why I'm not using a 2's compliment and just or'ing that bit instead... (edit: yep it appears broken)

another question, is the relative branch relative to the current address or the next one? In other words, if destAddr-currentAddr is zero, would that be en infinite loop or a no-op?
This should be self-evident given the example usage I added. It's relative to the address of the instruction doing the branching.

Anyway, do what you want with the code. I posted it because I use it regularly and know absolutely it is reliable. About the most you'll get me to agree to is that the mask can be simplified from 0x3f.. to 0x1f...

edit:
bonus round... in a 32bit address system, is 0x80000000 address negative zero, or what? xD (it's much more work to mask that bit out and convert to int than to just deal with it as a pair of positive u32)

edit2: manual checks with a disassembler just now, don't rely on backwards branching... I have no idea why it worked when I tested it on the console as disassembly of manually built instructions does not.

Some messy casting that simplifies and should work (tested, previous way was definitely broken on backwards links)
Code:
u32 makeBranch(u32 currAddr, u32 destAddr, bool linked, /*bool abs*/)
{
    s32 dist = ((int)(destAddr&~0x80000000)) - ((int)(currAddr&~0x80000000));
    u32 ret = 0x48000000 | ((u32)(dist&0x3FFFFFC));
    if(linked)
        ret = ret|1;
//    if(abs) // just for fun... use currAddr as 0 and destAddr as the absolute
//        ret = ret|2
    return ret;
}
/* working, proof:
old: branch 0x80000010 to 0x80000024 = 48000014
new: branch 0x80000010 to 0x80000024 = 48000014
 
old: branch 0x80000024 to 0x80000010 = 4a000014 << definitely not right
new: branch 0x80000024 to 0x80000010 = 4bffffec << definitely right
*/
Thanks Maxternal for making me look at this again sideways, you probably saved me a few hours debugging if/when I inadvertantly use a backwards branch without knowing it outright :D
 
  • Like
Reactions: Maxternal

Site & Scene News

Popular threads in this forum

General chit-chat
Help Users
    K3Nv2 @ K3Nv2: I have imaginary enemies