void test_basic_patching(void) { extern unsigned int ftr_fixup_test1; extern unsigned int end_ftr_fixup_test1; extern unsigned int ftr_fixup_test1_orig; extern unsigned int ftr_fixup_test1_expected; int size = &end_ftr_fixup_test1 - &ftr_fixup_test1; fixup.value = fixup.mask = 8; fixup.start_off = calc_offset(&fixup, &ftr_fixup_test1 + 1); fixup.end_off = calc_offset(&fixup, &ftr_fixup_test1 + 2); fixup.alt_start_off = fixup.alt_end_off = 0; /* Sanity check */ check(memcmp(&ftr_fixup_test1, &ftr_fixup_test1_orig, size) == 0); /* Check we don't patch if the value matches */ patch_feature_section(8, &fixup); check(memcmp(&ftr_fixup_test1, &ftr_fixup_test1_orig, size) == 0); /* Check we do patch if the value doesn't match */ patch_feature_section(0, &fixup); check(memcmp(&ftr_fixup_test1, &ftr_fixup_test1_expected, size) == 0); /* Check we do patch if the mask doesn't match */ memcpy(&ftr_fixup_test1, &ftr_fixup_test1_orig, size); check(memcmp(&ftr_fixup_test1, &ftr_fixup_test1_orig, size) == 0); patch_feature_section(~8, &fixup); check(memcmp(&ftr_fixup_test1, &ftr_fixup_test1_expected, size) == 0); }
static void test_alternative_case_too_big(void) { extern unsigned int ftr_fixup_test3; extern unsigned int end_ftr_fixup_test3; extern unsigned int ftr_fixup_test3_orig; extern unsigned int ftr_fixup_test3_alt; int size = &end_ftr_fixup_test3 - &ftr_fixup_test3; fixup.value = fixup.mask = 0xC; fixup.start_off = calc_offset(&fixup, &ftr_fixup_test3 + 1); fixup.end_off = calc_offset(&fixup, &ftr_fixup_test3 + 2); fixup.alt_start_off = calc_offset(&fixup, &ftr_fixup_test3_alt); fixup.alt_end_off = calc_offset(&fixup, &ftr_fixup_test3_alt + 2); /* Sanity check */ check(memcmp(&ftr_fixup_test3, &ftr_fixup_test3_orig, size) == 0); /* Expect nothing to be patched, and the error returned to us */ check(patch_feature_section(0xF, &fixup) == 1); check(memcmp(&ftr_fixup_test3, &ftr_fixup_test3_orig, size) == 0); check(patch_feature_section(0, &fixup) == 1); check(memcmp(&ftr_fixup_test3, &ftr_fixup_test3_orig, size) == 0); check(patch_feature_section(~0xF, &fixup) == 1); check(memcmp(&ftr_fixup_test3, &ftr_fixup_test3_orig, size) == 0); }
static void test_alternative_case_too_small(void) { extern unsigned int ftr_fixup_test4; extern unsigned int end_ftr_fixup_test4; extern unsigned int ftr_fixup_test4_orig; extern unsigned int ftr_fixup_test4_alt; extern unsigned int ftr_fixup_test4_expected; int size = &end_ftr_fixup_test4 - &ftr_fixup_test4; unsigned long flag; /* Check a high-bit flag */ flag = 1UL << ((sizeof(unsigned long) - 1) * 8); fixup.value = fixup.mask = flag; fixup.start_off = calc_offset(&fixup, &ftr_fixup_test4 + 1); fixup.end_off = calc_offset(&fixup, &ftr_fixup_test4 + 5); fixup.alt_start_off = calc_offset(&fixup, &ftr_fixup_test4_alt); fixup.alt_end_off = calc_offset(&fixup, &ftr_fixup_test4_alt + 2); /* Sanity check */ check(memcmp(&ftr_fixup_test4, &ftr_fixup_test4_orig, size) == 0); /* Check we don't patch if the value matches */ patch_feature_section(flag, &fixup); check(memcmp(&ftr_fixup_test4, &ftr_fixup_test4_orig, size) == 0); /* Check we do patch if the value doesn't match */ patch_feature_section(0, &fixup); check(memcmp(&ftr_fixup_test4, &ftr_fixup_test4_expected, size) == 0); /* Check we do patch if the mask doesn't match */ memcpy(&ftr_fixup_test4, &ftr_fixup_test4_orig, size); check(memcmp(&ftr_fixup_test4, &ftr_fixup_test4_orig, size) == 0); patch_feature_section(~flag, &fixup); check(memcmp(&ftr_fixup_test4, &ftr_fixup_test4_expected, size) == 0); }
static void test_alternative_patching(void) { extern unsigned int ftr_fixup_test2; extern unsigned int end_ftr_fixup_test2; extern unsigned int ftr_fixup_test2_orig; extern unsigned int ftr_fixup_test2_alt; extern unsigned int ftr_fixup_test2_expected; int size = &end_ftr_fixup_test2 - &ftr_fixup_test2; fixup.value = fixup.mask = 0xF; fixup.start_off = calc_offset(&fixup, &ftr_fixup_test2 + 1); fixup.end_off = calc_offset(&fixup, &ftr_fixup_test2 + 2); fixup.alt_start_off = calc_offset(&fixup, &ftr_fixup_test2_alt); fixup.alt_end_off = calc_offset(&fixup, &ftr_fixup_test2_alt + 1); /* Sanity check */ check(memcmp(&ftr_fixup_test2, &ftr_fixup_test2_orig, size) == 0); /* Check we don't patch if the value matches */ patch_feature_section(0xF, &fixup); check(memcmp(&ftr_fixup_test2, &ftr_fixup_test2_orig, size) == 0); /* Check we do patch if the value doesn't match */ patch_feature_section(0, &fixup); check(memcmp(&ftr_fixup_test2, &ftr_fixup_test2_expected, size) == 0); /* Check we do patch if the mask doesn't match */ memcpy(&ftr_fixup_test2, &ftr_fixup_test2_orig, size); check(memcmp(&ftr_fixup_test2, &ftr_fixup_test2_orig, size) == 0); patch_feature_section(~0xF, &fixup); check(memcmp(&ftr_fixup_test2, &ftr_fixup_test2_expected, size) == 0); }
void do_feature_fixups(unsigned long value, void *fixup_start, void *fixup_end) { struct fixup_entry *fcur, *fend; fcur = fixup_start; fend = fixup_end; for (; fcur < fend; fcur++) { if (patch_feature_section(value, fcur)) { WARN_ON(1); printk("Unable to patch feature section at %p - %p" \ " with %p - %p\n", calc_addr(fcur, fcur->start_off), calc_addr(fcur, fcur->end_off), calc_addr(fcur, fcur->alt_start_off), calc_addr(fcur, fcur->alt_end_off)); } } }