/* SPDX-License-Identifier: GPL-2.0-only */ /* This file is part of the coreboot project. */ #include enum { /* test patterns */ PATTERN0 = 0x00000000, PATTERN1 = 0x5A5A5A5A, PATTERN2 = 0xA5A5A5A5, PATTERN3 = 0xA5A5A500, PATTERN4 = 0xA500A500, PATTERN5 = 0xA5000000, PATTERN6 = 0xFFFF0000, PATTERN7 = 0x0000FFFF, PATTERN8 = 0x00000012, PATTERN9 = 0x00000034, PATTERNA = 0x00000056, PATTERNB = 0x00000078, PATTERNC = 0x00001234, PATTERND = 0x00005678, PATTERNE = 0x12345678, PATTERNF = 0xFFFFFFFF }; int complex_mem_test(u8 *start, unsigned int len) { unsigned char *mem8_base = (unsigned char *)start; unsigned short *mem16_base = (unsigned short *)start; unsigned int *mem32_base = (unsigned int *)start; unsigned int *mem_base = (unsigned int *)start; unsigned char pattern8; unsigned short pattern16; unsigned int i, j, size, pattern32; unsigned int value; uintptr_t p; size = len >> 2; /* verify the tied bits (tied high) */ for (i = 0; i < size; i++) mem32_base[i] = PATTERN0; for (i = 0; i < size; i++) { if (mem32_base[i] != PATTERN0) return -1; mem32_base[i] = PATTERNF; } /* verify the tied bits (tied low) */ for (i = 0; i < size; i++) { if (mem32_base[i] != PATTERNF) return -2; mem32_base[i] = PATTERN0; } /* verify pattern 1 (0x00~0xff) */ pattern8 = PATTERN0; for (i = 0; i < len; i++) mem8_base[i] = pattern8++; pattern8 = PATTERN0; for (i = 0; i < len; i++) { if (mem8_base[i] != pattern8++) return -3; } /* verify pattern 2 (0x00~0xff) */ pattern8 = PATTERN0; for (i = j = 0; i < len; i += 2, j++) { if (mem8_base[i] == pattern8) mem16_base[j] = pattern8; if (mem16_base[j] != pattern8) return -4; pattern8 += 2; } /* verify pattern 3 (0x00~0xffff) */ pattern16 = PATTERN0; for (i = 0; i < (len >> 1); i++) mem16_base[i] = pattern16++; pattern16 = PATTERN0; for (i = 0; i < (len >> 1); i++) { if (mem16_base[i] != pattern16++) return -5; } /* verify pattern 4 (0x00~0xffffffff) */ pattern32 = PATTERN0; for (i = 0; i < (len >> 2); i++) mem32_base[i] = pattern32++; pattern32 = PATTERN0; for (i = 0; i < (len >> 2); i++) { if (mem32_base[i] != pattern32++) return -6; } /* pattern 5: filling memory range with 0x12345678 */ for (i = 0; i < size; i++) mem32_base[i] = PATTERNE; /* read check then fill memory with a5a5a5a5 pattern */ for (i = 0; i < size; i++) { if (mem32_base[i] != PATTERNE) return -7; mem32_base[i] = PATTERN2; } /* read check then fill memory with 00 byte pattern at offset 0h */ for (i = 0; i < size; i++) { if (mem32_base[i] != PATTERN2) return -8; mem8_base[i * 4] = PATTERN0; } /* read check then fill memory with 00 byte pattern at offset 2h */ for (i = 0; i < size; i++) { if (mem32_base[i] != PATTERN3) return -9; mem8_base[i * 4 + 2] = PATTERN0; } /* read check then fill memory with 00 byte pattern at offset 1h */ for (i = 0; i < size; i++) { if (mem32_base[i] != PATTERN4) return -10; mem8_base[i * 4 + 1] = PATTERN0; } /* read check then fill memory with 00 byte pattern at offset 3h */ for (i = 0; i < size; i++) { if (mem32_base[i] != PATTERN5) return -11; mem8_base[i * 4 + 3] = PATTERN0; } /* read check then fill memory with ffff word pattern at offset 1h */ for (i = 0; i < size; i++) { if (mem32_base[i] != PATTERN0) return -12; mem16_base[i * 2 + 1] = PATTERN7; } /* read check then fill memory with ffff word pattern at offset 0h */ for (i = 0; i < size; i++) { if (mem32_base[i] != PATTERN6) return -13; mem16_base[i * 2] = PATTERN7; } /* read check */ for (i = 0; i < size; i++) { if (mem32_base[i] != PATTERNF) return -14; } /* stage 1 => write 0 */ for (i = 0; i < size; i++) mem_base[i] = PATTERN1; /* stage 2 => read 0, write 0xf */ for (i = 0; i < size; i++) { value = mem_base[i]; if (value != PATTERN1) return -15; mem_base[i] = PATTERN2; } /* stage 3 => read 0xf, write 0 */ for (i = 0; i < size; i++) { value = mem_base[i]; if (value != PATTERN2) return -16; mem_base[i] = PATTERN1; } /* stage 4 => read 0, write 0xf */ for (i = 0; i < size; i++) { value = mem_base[i]; if (value != PATTERN1) return -17; mem_base[i] = PATTERN2; } /* stage 5 => read 0xf, write 0 */ for (i = 0; i < size; i++) { value = mem_base[i]; if (value != PATTERN2) return -18; mem_base[i] = PATTERN1; } /* stage 6 => read 0 */ for (i = 0; i < size; i++) { value = mem_base[i]; if (value != PATTERN1) return -19; } /* 1/2/4-byte combination test */ p = (uintptr_t)mem_base; while (p < (uintptr_t)mem_base + (size << 2)) { *((unsigned char *)p) = PATTERNB; p += 1; *((unsigned char *)p) = PATTERNA; p += 1; *((unsigned short *)p) = PATTERNC; p += 2; *((unsigned int *)p) = PATTERNE; p += 4; *((unsigned short *)p) = PATTERND; p += 2; *((unsigned char *)p) = PATTERN9; p += 1; *((unsigned char *)p) = PATTERN8; p += 1; *((unsigned int *)p) = PATTERNE; p += 4; *((unsigned char *)p) = PATTERNB; p += 1; *((unsigned char *)p) = PATTERNA; p += 1; *((unsigned short *)p) = PATTERNC; p += 2; *((unsigned int *)p) = PATTERNE; p += 4; *((unsigned short *)p) = PATTERND; p += 2; *((unsigned char *)p) = PATTERN9; p += 1; *((unsigned char *)p) = PATTERN8; p += 1; *((unsigned int *)p) = PATTERNE; p += 4; } for (i = 0; i < size; i++) { value = mem_base[i]; if (value != PATTERNE) return -20; } /* verify pattern 1 (0x00~0xff) */ pattern8 = PATTERN0; mem8_base[0] = pattern8; for (i = 0; i < size * 4; i++) { unsigned char waddr8, raddr8; waddr8 = i + 1; raddr8 = i; if (i < size * 4 - 1) mem8_base[waddr8] = pattern8 + 1; if (mem8_base[raddr8] != pattern8) return -21; pattern8++; } /* verify pattern 2 (0x00~0xffff) */ pattern16 = PATTERN0; mem16_base[0] = pattern16; for (i = 0; i < size * 2; i++) { if (i < size * 2 - 1) mem16_base[i + 1] = pattern16 + 1; if (mem16_base[i] != pattern16) return -22; pattern16++; } /* verify pattern 3 (0x00~0xffffffff) */ pattern32 = PATTERN0; mem32_base[0] = pattern32; for (i = 0; i < size; i++) { if (i < size - 1) mem32_base[i + 1] = pattern32 + 1; if (mem32_base[i] != pattern32) return -23; pattern32++; } return 0; }