/* /* phat patch! woo -bushing */ #include #include #include #include #include #include #include #define WRITE_ADDR(x,y) flash[((x & 0x7FFF)<<1) | ((x & 0x8000) >> 15)]=(y) #define READ_ADDR(x) flash[((x & 0x7FFF)<<1) | ((x & 0x8000) >> 15)] struct patch_struct { char *desc; unsigned int byte_offset; unsigned short original_word1, original_word2, new_word1, new_word2; }; struct patch_struct volvo_patches[] = { {"make drive signature check always succeed: [bne verify_sig_failed -> bne PC+1]", 0x0D90, 0x0033, 0x1A00, 0x0000, 0x1A00}, {"make rc.sh signature check always succeed: [bne verify_sig_failed -> bne PC+1]", 0x0DC4, 0x0026, 0x1A00, 0x0000, 0x1A00}, {"make phatd signature check always succeed: [bne verify_sig_failed -> bne PC+1]", 0x0DF8, 0x0019, 0x1A00, 0x0000, 0x1A00}, {"make linux signature check always succeed: [bne verify_sig_failed -> bne PC+1]", 0x0E2C, 0x000C, 0x1A00, 0x0000, 0x1A00}, {"make ramdisk invalid signature return 0 instead of 0xFFFFFFFF: [movlne r0, 0xFFFFFFFF -> movlne r0, #0]", 0x051C, 0x0000, 0x13E0, 0x0000, 0x13A0}, {"make ramdisk signature check verify 0 instead of 1: [cmp r0, #1 -> cmp r0, #0]", 0x0E58, 0x0001, 0xE350, 0x0000, 0xE350}, {"make ramdisk valid signature return 0 instead of 1: [moveq r0, #1 -> moveq r0, #0]", 0x0520, 0x0001, 0x03A0, 0x0000, 0x03A0}, {"don't try to read ramdisk.sig (boot without any .sig files): [bl sector_read_suzy -> bl PC+1]", 0x04F4, 0x02E0, 0xEB00, 0x0000, 0xEB00}, {"don't try to read linux.sig (boot without any .sig files): [bl sector_read_suzy -> bl PC+1]", 0x0460, 0x0305, 0xEB00, 0x0000, 0xEB00} }; struct patch_struct standard_patches[] = { {"make drive signature check always succeed: [bne verify_sig_failed -> bne PC+1]", 0x0BB8, 0x0033, 0x1A00, 0x0000, 0x1A00}, {"make rc.sh signature check always succeed: [bne verify_sig_failed -> bne PC+1]", 0x0BEC, 0x0026, 0x1A00, 0x0000, 0x1A00}, {"make phatd signature check always succeed: [bne verify_sig_failed -> bne PC+1]", 0x0C20, 0x0019, 0x1A00, 0x0000, 0x1A00}, {"make linux signature check always succeed: [bne verify_sig_failed -> bne PC+1]", 0x0C54, 0x000C, 0x1A00, 0x0000, 0x1A00}, {"make ramdisk invalid signature return 0 instead of 0xFFFFFFFF: [movlne r0, 0xFFFFFFFF -> movlne r0, #0]", 0x0354, 0x0000, 0x13E0, 0x0000, 0x13A0}, {"make ramdisk signature check verify 0 instead of 1: [cmp r0, #1 -> cmp r0, #0]", 0x0C80, 0x0001, 0xE350, 0x0000, 0xE350}, {"make ramdisk valid signature return 0 instead of 1: [moveq r0, #1 -> moveq r0, #0]", 0x0358, 0x0001, 0x03A0, 0x0000, 0x03A0}, {"don't try to read ramdisk.sig (boot without any .sig files): [bl sector_read_suzy -> bl PC+1]", 0x0330, 0x02DB, 0xEB00, 0x0000, 0xEB00}, {"don't try to read linux.sig (boot without any .sig files): [bl sector_read_suzy -> bl PC+1]", 0x02C0, 0x02F7, 0xEB00, 0x0000, 0xEB00} }; int num_patches; struct patch_struct *chose_patches(volatile unsigned short *flash) { int verified,i; printf("Finding patch offsets:\n"); verified=1; fflush(NULL); num_patches=sizeof(standard_patches)/sizeof(struct patch_struct); for(i=0;i= count) break; // Only apply N patches -- this way we can automagically corrupt the ramdisk sig when necessary printf("Patch %d @ %04x: %s\n",i+1,patches[i].byte_offset, patches[i].desc); fflush(NULL); printf("Expected: %04x %04x Actual: %04x %04x\n", patches[i].original_word1, patches[i].original_word2, flash[patches[i].byte_offset/2], flash[patches[i].byte_offset/2+1]); fflush(NULL); if(patches[i].original_word1==flash[patches[i].byte_offset/2] && patches[i].original_word2==flash[patches[i].byte_offset/2+1]) { printf("Match! Programming...\n"); fflush(NULL); if(patches[i].original_word1!=patches[i].new_word1) { WRITE_ADDR(uaddr1,0xaa); WRITE_ADDR(uaddr2,0x55); WRITE_ADDR(uaddr1,0xa0); flash[patches[i].byte_offset/2]=patches[i].new_word1; sleep(2); fflush(NULL); while(flash[patches[i].byte_offset/2]!=patches[i].new_word1) { printf("Waiting...\n"); fflush(NULL); } printf("Wrote %04x\n",patches[i].new_word1); } if(patches[i].original_word2!=patches[i].new_word2) { WRITE_ADDR(uaddr1,0xaa); WRITE_ADDR(uaddr2,0x55); WRITE_ADDR(uaddr1,0xa0); flash[patches[i].byte_offset/2+1]=patches[i].new_word2; sleep(2); fflush(NULL); while(flash[patches[i].byte_offset/2+1]!=patches[i].new_word2) { printf("Waiting...\n"); fflush(NULL); } printf("Wrote %04x\n",patches[i].new_word2); } } else { if (flash[patches[i].byte_offset/2]==patches[i].new_word1 && flash[patches[i].byte_offset/2+1]==patches[i].new_word2) { printf("Detected patch %d already applied\n", i+1); } else { printf("Mismatch!\n"); } fflush(NULL); } sleep(2); } break; case 'v': printf("Verifying:\n"); count=0; fflush(NULL); for(i=0;i