You are viewing our Forum Archives. To view or take place in current topics click here.
#11. Posted:
Status: Offline
Joined: Nov 29, 201014Year Member
Posts: 1,902
Reputation Power: 102
Status: Offline
Joined: Nov 29, 201014Year Member
Posts: 1,902
Reputation Power: 102
i think youre on to something there great post
- 0useful
- 0not useful
#12. Posted:
Status: Offline
Joined: Dec 22, 200915Year Member
Posts: 5,352
Reputation Power: 461
Status: Offline
Joined: Dec 22, 200915Year 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.
I hope this is useful and maybe once the next dashboard lauches, this can all be used beneficially.
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.
- 0useful
- 0not useful
You are viewing our Forum Archives. To view or take place in current topics click here.