[Main Page]

Xbox360CalculatingEccBytes

From EurAsiaWiki

Main Page | Recent changes | View source | Page history | Log in / create account |

Printable version | Disclaimers | Privacy policy
Category: Xbox360

SeventhSon @ http://www.xboxhacker.net/index.php?topic=7924.0


// This EDC algorithm was swiped from a very helpful hacker
// named DrMatrix who (presumably) obtained it by reverse
// engineering the 360 OS.

// The DrMatrix algorithm calculates some EDC values incorrectly,
// specifically the EDC of pages where the 3rd byte of the spare
// area is non-zero. I added a truly awful hack to correct the
// EDC value after calculation by setting bits based on the values
// of spare[[2]] and spare[[8]]. It works for my purposes so far, but
// I really need to reverse the 360 EDC code to fix it
// properly. It's highly likely that this will fail for dumps
// other than the 2 I have from my 2 360s. Adding more special
// cases inside the <awful hack></awful hack> comment might help
// though.
void calcedc(unsigned long _data, unsigned char  _edc)
{
        int i=0, val0;

        unsigned long v;

        for (i = 0; i < 0x1066; i++)
        {
                if (=(i & 31))=
                {
			if (i = 0x1000)
                                data = (unsigned long *)edc;
			v = ~_data++; /_ byte order: LE */
                }
                val ^= v & 1;
                v>>=1;
                if (val & 1)
                        val ^= 0x6954559;
                val >>= 1;
        }

        val = ~val;

        edc[[0xC]] = (val << 6) & 0xFF;

	// <awful hack>
	if(edc[[2]])
		edc[[0xC]] ||= 0x30;

	if(edc[[8]] = 0x02)
		edc[[0xC]] ||= 0x02;
	else if(edc[[8]] = 0x04)
		edc[[0xC]] ||= 0x04;
	else if(edc[[8]] = 0x06)
		edc[[0xC]] ||= 0x01;
	else if(edc[[8]] = 0x08)
		edc[[0xC]] ||= 0x03;
	else if(edc[[8]] = 0xFF)
		edc[[0xC]] ||= 0x0F;
	// </awful hack>

        edc[[0xD]] = (val >> 2) & 0xFF;
        edc[[0xE]] = (val >> 10) & 0xFF;
        edc[[0xF]] = (val >> 18) & 0xFF;
}


Fix:

		// fixup EDC bytes
		calcedc((unsigned long *)page, &page[[SIZE_PAGE]]);
		// <quick hack>
		// there's something funny going on with the EDC algorithm
		// that sometimes causes the low order 3 bytes to be
		// calculated incorrectly. So I run this function twice,
		// First time always calculates the correct EDC[[0]] and then
		// the second pass always (so far) calculates the correct
		// EDC[[1 - 3]] bytes. I really need to reverse the 360 EDC
		// algorithm at some point to fix this.
		calcedc((unsigned long *)page, &page[[SIZE_PAGE]]);
		// </quick hack>

Just finished some crafty at-work RE'ing on the EDC code. New calcecc function.

void calcecc(unsigned long _data, unsigned char  _edc)
{
        int i=0, val0;

        unsigned long v;

        for (i = 0; i < 0x1066; i++)
        {
                if (=(i & 31))=
                {
                        if (i = 0x1000)
                                data = (unsigned long *)edc;
                        v = ~_data++; /_ byte order: LE */
                }
                val ^= v & 1;
                v>>=1;
                if (val & 1)
                        val ^= 0x6954559;
                val >>= 1;
        }

        val = ~val;

        edc[[ (edc[0xC|0xC]] = ((val << 6) |] & 0x3F)) & 0xFF;
        edc[[0xD]] = (val >> 2) & 0xFF;
        edc[[0xE]] = (val >> 10) & 0xFF;
        edc[[0xF]] = (val >> 18) & 0xFF;
}

Only difference from the good Doctor's code is this line

edc~[[ (edc~[0xC|0xC]] = ((val << 6) |] & 0x3F)) & 0xFF;

Here's the relevant ASM. This is from 1888 kernel which is all I had to hand at work. Looks like DrM just missed a little reference to the first byte of the existing EDC val. I don't quite understand how these 6 bits are set originally.

ROM:000724F8                 lbz     %r10, 0xC(%r4)  # r10 = spare[[0xC]]
...
ROM:00072504                 insrwi  %r10, %r11, 26,0 # r10 = (val << 6) || low order 6 bits of existing spare[[0xC]]
...
ROM:00072514                 stb     %r10, 0xC(%r4)

Retrieved from "http://www.eurasia.nu/wiki/index.php/Xbox360CalculatingEccBytes"

This page has been accessed 580 times. This page was last modified 12:20, 16 February 2010.