You are viewing our Forum Archives. To view or take place in current topics click here.
#11. Posted:
Mini-Uzi
  • TTG Senior
Status: Offline
Joined: Nov 29, 201013Year Member
Posts: 1,902
Reputation Power: 102
Status: Offline
Joined: Nov 29, 201013Year Member
Posts: 1,902
Reputation Power: 102
i think youre on to something there great post
#12. Posted:
Colorado880
  • TTG Undisputed
Status: Offline
Joined: Dec 22, 200914Year Member
Posts: 5,352
Reputation Power: 461
Status: Offline
Joined: Dec 22, 200914Year Member
Posts: 5,352
Reputation Power: 461
Nice post. Now somehow we have to use this to maybe make another rebooter once the next update launches. (This Spring)

I've been researching a little bit about how freeBOOT runs and this is what I got so far.

First you need to control the whole hypervisor upon booting. Once the hypervisor is accesed, the console softboots into the new rebooter (XBR/freeBOOT) thus allowing you to run the unsigned code.

In order to make a new rebooter, you need to remap all the protocols and adresses to the 12625 kernel. After this is done, we would need to start creating patches


Here is arnezami post on XBH about rebooters.


Essentially the rebooting starts when all cpus are catched by the Xell loader and there is a jump to the reboot routine in the startup2.S. The idea is to do the same things that are normally done in the 1BL and CB to get the cpu into the same state as it was during boot.

First things that happen is a POST output of 0x40, re-setting of the memory mapping for CD, preparing the new position for CD for execution and copying CD into the position it normally would be during normal boot:

01310388                 li      %r3, 0x200
0131038C                 oris    %r3, %r3, 0x8000
01310390                 rldicr  %r3, %r3, 32,31
01310394                 oris    %r3, %r3, 6
01310398                 li      %r4, 0x40           // POST 0x40
0131039C                 rldicr  %r4, %r4, 56,7
013103A0                 std     %r4, 0x1010(%r3)
013103A4                 slbia                       // re-set all mappings (as in 1BL: 0x3060)
013103A8                 isync
013103AC                 li      %r3, 0x100
013103B0                 lis     %r4, 0x800
013103B4                 slbmte  %r3, %r4           
013103B8                 isync
013103BC                 li      %r3, 0
013103C0                 oris    %r3, %r3, 0x8000
013103C4                 rldicr  %r3, %r3, 32,31
013103C8                 lis     %r3, 0x131
013103CC                 addis   %r3, %r3, 1
013103D0                 ori     %r3, %r3, 0x6800    // source CD position: 0x8000000001326800
013103D4                 mr      %r6, %r3
013103D8                 li      %r3, 0x17C
013103DC                 oris    %r3, %r3, 0x8000
013103E0                 rldicr  %r3, %r3, 32,31
013103E4                 oris    %r3, %r3, 0x400     // target CD position: 0x8000017C04000000
013103E8                 mr      %r31, %r3
013103EC                 li      %r0, 0
013103F0                 li      %r4, 0x200
013103F4                 mtctr   %r4
013103F8                 dbcz128 %r0, %r3            // prep mem for execution (as in CB: 0x740)
013103FC                 addi    %r3, %r3, 0x80
01310400                 bdnz    loc_13103F8
01310404                 mr      %r3, %r31
01310408                 li      %r4, 0x1300
0131040C                 mtctr   %r4
01310410                 ld      %r5, 0(%r6)
01310414                 std     %r5, 0(%r3)           // copy CD
01310418                 addi    %r3, %r3, 8
0131041C                 addi    %r6, %r6, 8
01310420                 bdnz    loc_1310410
01310424                 li      %r3, 0x17C
01310428                 oris    %r3, %r3, 0
0131042C                 rldicr  %r3, %r3, 32,31
01310430                 oris    %r3, %r3, 0x400
01310434                 mtspr   0x139, %r3          // set hrmor to 0000017C04000000 (old: not required)


Normally when CD is started (during normal boot) %31 contains the position of CE in the nand (without counting edc bytes). I've made sure the makereboot program writes this CE position almost at the beginning of the execution code (at 0x1310004 if loaded through a disc, 0x1300004 for serial). So:

01310438                 lis     %r4, 0x131
0131043C                 ori     %r4, %r4, 4
01310440                 lwz     %r4, 0(%r4)           // load CE position at 0x1310004
01310444                 mr      %r31, %r4


Then some cleanup before jumping to CD:

01310448                 li      %r3, 0x17C
0131044C                 oris    %r3, %r3, 0x8000
01310450                 rldicr  %r3, %r3, 32,31
01310454                 oris    %r3, %r3, 0x400
01310458                 li      %r4, 0x200
0131045C                 mtctr   %r4
01310460                 dcbst   %r0, %r3
01310464                 addi    %r3, %r3, 0x80
01310468                 bdnz    loc_1310460
0131046C                 sync    0
01310470                 isync
01310474                 li      %r3, 0x408
01310478                 li      %r4, 0x17C
0131047C                 rldicr  %r4, %r4, 32,31
01310480                 oris    %r4, %r4, 0x400
01310484                 ori     %r4, %r4, 0x193
01310488                 li      %r5, 0x405
0131048C                 mtspr   0x3B3, %r3
01310490                 mtspr   0x3B5, %r4
01310494                 isync
01310498                 mtspr   0x3B4, %r5
0131049C                 isync
013104A0                 ...               // not blr !! (as in CB:0x6A6C)


Note that this is the same as being done at CB: 0x6A14 and it basicly flushes cache etc (not sure what the other special registers are for, just replicating as much as possible).

There is of course one big difference to what happens normally in CB. ;) At CB: 0x6A6C there is a blr which effectively is a branch to the (instruction) memory mapped start of CD which is 0x04000260 (see mtlr at CB: 0x69E0). But since we are not in memory mapped mode (instruction addresses aren't translated) we can't use this technique. What needs to done is to jump into CD and also turn on address translation (for instructions only). So thats done here with an rfid:

013104A0                 li      %r4, 0x260
013104A4                 oris    %r4, %r4, 0x400
013104A8                 mfmsr   %r3
013104AC                 ori     %r3, %r3, 0x20      // Turn on translation for instructions only (IR)
013104B0                 li      %r7, 0x1000
013104B4                 andc    %r3, %r3, %r7       // (just in case: turn off ME)
013104B8                 mtsrr1  %r3
013104BC                 mtsrr0  %r4
013104C0                 rfid


Keep in mind the address put in srr0 is 0x04000260 which is not a real address but only works in translated mode.

Now the above is needed to start CD. But because CB also adds some information (pairing data) to CD during normal boot I had to do the same. But instead of doing it on-the-fly I have already done this using the makereboot program. This pairing data is (during normal boot) copied from CB:0x20 to CD:0x20 and I do the same. Its three bytes long btw.

I also add the kernel/hv patcher to the CD with the makereboot program. And this is how it works in CD when its run. At 0x534 there is the function that jumps to the kernel. So right at the beginning of this sub I have put a branch to the patcher code (so patch at CD: 0x534, btw CD is loaded at 04000000 in IDA here).

04000534                 b       loc_40056F0      // patch
04000538                 lis     %r3, 0x28
0400053C                 li      %r4, 0x2A00
04000540                 mtctr   %r4
04000544                 dcbst   %r0, %r3
04000548                 icbi    %r0, %r3
0400054C                 addi    %r3, %r3, 0x80
04000550                 bdnz    loc_4000544
04000554                 sync    0
04000558                 isync
0400055C                 li      %r3, 0
04000560                 mtspr   0x130, %r3
04000564                 mtspr   0x131, %r3
04000568                 li      %r3, 0x3FF
0400056C                 rldicr  %r3, %r3, 32,31
04000570                 tlbiel  %r3, 1
04000574                 sync    0
04000578                 li      %r4, 0x100
0400057C                 rldicr  %r4, %r4, 32,31
04000580                 mfmsr   %r5
04000584                 li      %r6, 0x30          // real mode (translation off)
04000588                 andc    %r5, %r5, %r6
0400058C                 mtsrr1  %r5
04000590                 li      %r6, 0x100
04000594                 mtsrr0  %r6
04000598                 nop
0400059C                 nop
040005A0                 nop
040005A4                 mtspr   0x139, %r4
040005A8                 rfid                       // jump to hv


At 0x56F0 there is the (simple) patcher code:

040056F0                 li      %r3, 0x5800
040056F4                 oris    %r3, %r3, 0x400
040056F8                 lwz     %r4, 0(%r3)         // read amount of patches at 0x04005800
040056FC                 cmplwi  cr6, %r4, 0
04005700                 beq     cr6, loc_4005720
04005704                 mtctr   %r4
04005708                 addi    %r3, %r3, 4
0400570C                 lwz     %r4, 0(%r3)         // read address in hv/kernel
04005710                 lwz     %r5, 4(%r3)         // read new value
04005714                 stw     %r5, 0(%r4)         // store in hv/kernel
04005718                 addi    %r3, %r3, 8
0400571C                 bdnz    loc_400570C
04005720                 nop
04005724                 nop
04005728                 nop
0400572C                 lis     %r3, 0x28
04005730                 b       loc_4000538


All this does is read from 0x04005800 which contains the number of patches and then reads the first 4 bytes (which is the address in the kernel/hv) and reads the next 4 bytes (which is the new value) and stores it in the kernel/hv. And it does so for as many patches as were put in by the makereboot program. The kernel/hv is mapped at 0x00000000 so that made my life a lot easier .

When its done patching, it restores the instruction that was patched away (lis %r3, 0x28) and branches back to where it was (0x538). Then it jumps to the hv of course by the rfid at 0x5A8 (see above).

And thats it ;D. Thats how the rebooter works.

Well almost. There is also the entering of the other cpus into the hv. This is not spectacular but noteworthy. The other cpus look at a memory address that is changed by the HV (by cpu 0 doing SC 01). So I let the other cpus check this address:

01310140                 li      %r30, 1
01310144                 li      %r29, 0x200
01310148                 oris    %r29, %r29, 0x8000
0131014C                 rldicr  %r29, %r29, 32,31
01310150                 oris    %r29, %r29, 2
01310154                 slwi    %r3, %r30, 3
01310158                 subf    %r29, %r3, %r29     // address 0x800002000001FFF8


Right now this is hardcoded to 0x800002000001FFF8 but in fact for each core there is one value written to mem at a different position. I don't use that info now but instead simply use the jump code from CB: 0x7A0.

000007A0                 mfspr   %r3, l2cr
000007A4                 li      %r4, 1
000007A8                 rldimi  %r3, %r4, 48,15
000007AC                 li      %r4, 8
000007B0                 rldimi  %r3, %r4, 44,16
000007B4                 li      %r4, 0xE
000007B8                 rldimi  %r3, %r4, 34,26
000007BC                 isync
000007C0                 mtspr   l2cr, %r3
000007C4                 sync    0
000007C8                 isync
000007CC                 mfspr   %r3, 0x13E     
000007D0                 li      %r4, 1
000007D4                 rldimi  %r3, %r4, 1,62
000007D8                 isync
000007DC                 mtspr   0x13E, %r3
000007E0                 sync    0
000007E4                 isync
000007E8                 li      %r3, 0x3FF
000007EC                 rldicr  %r3, %r3, 32,31
000007F0                 tlbiel  %r3, 1
000007F4                 sync    0
000007F8                 mfspr   %r3, iac1
000007FC                 li      %r4, 0x3F # '?'
00000800                 rldimi  %r3, %r4, 40,18
00000804                 isync
00000808                 mtspr   iac1, %r3
0000080C                 sync    0
00000810                 isync
00000814                 li      %r3, 0
00000818                 mtspr   0x130, %r3
0000081C                 mtspr   0x131, %r3
00000820                 mfspr   %r3, 0x3F1
00000824                 li      %r4, 1
00000828                 rldimi  %r3, %r4, 63,0
0000082C                 li      %r4, 7
00000830                 rldimi  %r3, %r4, 58,3
00000834                 li      %r4, 3
00000838                 rldimi  %r3, %r4, 52,10
0000083C                 li      %r4, 1
00000840                 rldimi  %r3, %r4, 38,25
00000844                 li      %r4, 0x100
00000848                 rldicr  %r4, %r4, 32,31
0000084C                 mfmsr   %r5
00000850                 li      %r6, 0x30       // real mode (no translation anymore)
00000854                 andc    %r5, %r5, %r6
00000858                 mtsrr1  %r5             
0000085C                 li      %r6, 0x100
00000860                 mtsrr0  %r6             // Hypervisor enrty point 0x100
00000864                 nop
00000868                 nop
0000086C                 nop
00000870                 nop
00000874                 nop
00000878                 nop
0000087C                 nop
00000880                 mtspr   0x3F1, %r3
00000884                 mtspr   0x139, %r4      // HRMOR register = 00000100_00000000
00000888                 rfid                    // jump to hv


This might have to be changed. But for now it seems to work just fine. Although the pending IPI (Inter-processor interrupt) done in the hv might be giving trouble later on. Will have to investigate this at some time. But when it comes to interrupts (and controllers) I could certainly use some help.

Hope you enjoyed it.

Regards,

arnezami



I hope this is useful and maybe once the next dashboard lauches, this can all be used beneficially.
Jump to:
You are viewing our Forum Archives. To view or take place in current topics click here.