📄 btflash.c
字号:
0x01e80000, 0x01ec0000, 0x01f00000, 0x01f40000, 0x01f80000, 0x01fc0000, 0x02000000 /* guard sector */};static int intelFlashReset(void);static int intelFlashProgramBlock(unsigned long flashAddress, unsigned long *values, int nbytes);static int intelFlashProgramWord(unsigned long flashAddress, unsigned long value);static int intelFlashEraseChip(void);static int intelFlashEraseSector(unsigned long sectorAddress);static int intelFlashEraseRange(unsigned long start, unsigned long len);static int intelFlashProtectRange(unsigned long start, unsigned long len, int protect);static FlashAlgorithm intelFlashAlgorithm = { intelFlashReset, intelFlashProgramWord, intelFlashProgramBlock, intelFlashEraseChip, intelFlashEraseSector, intelFlashEraseRange, intelFlashProtectRange};static FlashDescriptor flashDescriptor_28F128J3A = { "28F128J3A", 0x89, 0x18, &intelFlashAlgorithm, sizeof(flashSectors_28F128J3A)/sizeof(dword) - 1, flashSectors_28F128J3A, { "bootldr", 0x00000000, 0x00040000, LFR_PATCH_BOOTLDR }, { "params", 0x000c0000, 0x00040000, 0 }, { "kernel", 0x00040000, 0x00080000, LFR_KERNEL }, { "ramdisk", 0x00100000, 0x00700000, LFR_SIZE_PREFIX }, { "usercode", 0x00100000, 0x00700000, 0 }, /* for flash cramfs */ { "altkernel", 0x00900000, 0x01100000, LFR_KERNEL }, { "debugger", 0x00900000, 0x01100000, 0 }};#endif /* CONFIG_INTEL_FLASH */static FlashDescriptor *flashDescriptors[] = {#ifdef CONFIG_AMD_FLASH &flashDescriptor_Am29LV160BB, &flashDescriptor_Am29DL323CT, &flashDescriptor_Am29DL323CB,#endif /* CONFIG_AMD_FLASH */#ifdef CONFIG_BITSY &flashDescriptor_28F128J3A,#endif /* CONFIG_BITSY */ NULL};long flash_size = 0;long flash_address_mask = -1;int nsectors = 0;unsigned long *flashSectors = NULL;FlashDescriptor *flashDescriptor = NULL;static int checkFlashDescriptor(const char *where){ if (flashDescriptor == NULL) { putstr("No flash descriptor: "); putstr(where); putstr("\r\n"); return -1; } else { return 0; }}int resetFlash (){ if (!checkFlashDescriptor("reset flash")) { return flashDescriptor->algorithm->reset(); } else { return 1; }}/* * Programs value at flashAddress * Sectors must be erased before they can be programmed. */int programFlashWord(unsigned long flashAddress, unsigned long value){ if (!checkFlashDescriptor("program flash word")) { return flashDescriptor->algorithm->programWord(flashAddress, value); } else { return 1; }}/* * Programs block of values starting at flashAddress * Sectors must be erased before they can be programmed. */int programFlashBlock(unsigned long flashAddress, unsigned long *values, int nbytes){ if (!checkFlashDescriptor("program flash word")) { return flashDescriptor->algorithm->programBlock(flashAddress, values, nbytes); } else { return 1; }}int eraseFlashChip (){ if (!checkFlashDescriptor("erase flash chip")) { return flashDescriptor->algorithm->eraseChip(); } else { return 1; }}/* sectorAddress must be a valid start of sector address. sectors must be erased before they can be programmed! */int eraseFlashSector (unsigned long sectorAddress){ if (!checkFlashDescriptor("erase flash sector")) { return flashDescriptor->algorithm->eraseSector(sectorAddress); } else { return 1; }}int eraseFlashRange(unsigned long startAddress, unsigned long len){ if (!checkFlashDescriptor("erase flash range")) { return flashDescriptor->algorithm->eraseRange(startAddress, len); } else { return 1; }}int protectFlashRange(unsigned long startAddress, unsigned long len, int protect){ if (!checkFlashDescriptor("erase flash range")) { return flashDescriptor->algorithm->protectRange(startAddress, len, protect); } else { return 1; }}unsigned long queryFlash(unsigned long flashWordAddress){ /* there's a reason why we don't shift flashWordOffset by 2 * here... we want the values we pass to queryFlash match the values on pages 15-17 of the spec. */ unsigned long result; unsigned long flashWordOffset = flashWordAddress&flash_address_mask; /* put flash in query mode */ flashword[0x55] = doubleword(0x98); result = flashword[flashWordOffset]; /* reset flash */ flashword[0x55] = doubleword(0xFF); return result;}static FlashAlgorithm *flashAlgorithm = NULL;int updateFlashAlgorithm(){ int algorithm = queryFlash(0x13) & 0xFF; switch (algorithm) {#ifdef CONFIG_INTEL_FLASH case 1: flashAlgorithm = &intelFlashAlgorithm; break;#endif#ifdef CONFIG_AMD_FLASH case 2: flashAlgorithm = &amdFlashAlgorithm; break;#endif default: putLabeledWord("No flash algorithm known for CFI vendorID=", algorithm); } return algorithm;}unsigned long queryFlashID(unsigned long flashWordAddress){ unsigned long result; unsigned long flashWordOffset = (flashWordAddress&flash_address_mask); int algorithm = queryFlash(0x13) & 0xFF; switch (algorithm) { case 1: /* reset flash -- Intel */ flashword[0x55] = doubleword(0xFF); /* put flash in query mode */ flashword[0x555] = doubleword(0x90); break; case 2: /* reset flash -- AMD */ flashword[0x55] = doubleword(0xF0); /* put flash in query mode */ flashword[0x555] = doubleword(0xAA); flashword[0x2AA] = doubleword(0x55); flashword[0x555] = doubleword(0x90); break; } /* read autoselect word */ result = flashword[flashWordOffset]; switch (algorithm) { case 1: /* reset flash -- Intel */ flashword[0x55] = doubleword(0xFF); break; case 2: /* reset flash -- AMD */ flashword[0x55] = doubleword(0xF0); break; } return result;}unsigned long queryFlashSecurity(unsigned long flashWordAddress){ /* there's a reason why we don't shift flashWordOffset by 2 * here... we want the values we pass to queryFlash match the values on pages 15-17 of the spec. */ unsigned long result; unsigned long flashWordOffset = (flashWordAddress&flash_address_mask); /* reset flash */ flashword[0x555] = doubleword(0xF0); flashword[0x555] = doubleword(0xF0); /* enter SecSi Sector Region */ flashword[0x555] = doubleword(0xAA); flashword[0x2AA] = doubleword(0x55); flashword[0x555] = doubleword(0x88); /* read word from SecSi region */ result = flashword[flashWordOffset]; /* exit region */ flashword[0x555] = doubleword(0xAA); flashword[0x2AA] = doubleword(0x55); flashword[0x555] = doubleword(0x90); flashword[0x000] = doubleword(0x00); return result;}#ifdef CONFIG_AMD_FLASHint amdFlashReset (){ /* send flash the reset command */ flashword[0x55] = doubleword(0xF0); return 0;}/* * Programs value at flashAddress * Sectors must be erased before they can be programmed. */static int amdFlashProgramWord(unsigned long flashAddress, unsigned long value){ unsigned long flashWordOffset = (flashAddress&flash_address_mask) >> 2; long timeout = FLASH_TIMEOUT; unsigned long flashContents = flashword[flashWordOffset]; unsigned long oldFlashContents; unsigned long hivalue = (value >> 16) & 0xFFFFl; unsigned long lovalue = (value >> 0) & 0xFFFFl; /* see if we can program the value without erasing */ if ((flashContents & value) != value) { putstr("the flash sector needs to be erased first!\r\n"); putLabeledWord(" flashAddress=", flashAddress); putLabeledWord(" flashWordOffset=", flashWordOffset); putLabeledWord(" &flashword[flashWordOffset]=", (dword)&flashword[flashWordOffset]); putLabeledWord(" flashContents=", flashContents); putLabeledWord(" value=", value); } /* send flash the program word command */ flashword[0x555] = doubleword(0xAA); flashword[0x2AA] = doubleword(0x55); flashword[0x555] = doubleword(0xA0); flashword[flashWordOffset] = value; /* now wait for it to be programmed */ while (((flashContents = flashword[flashWordOffset]) != value) && (timeout > 0)) { unsigned long hiword = (flashContents >> 16) & 0xFFFFl; unsigned long loword = (flashContents >> 0) & 0xFFFFl; if (0 && (hiword != hivalue) && (hiword & (1 << 5))) { /* programming upper bank of flash timed out */ putstr("Upper bank of flash timed out!!"); timeout = 0; break; } if (0 && (loword != lovalue) && (loword & (1 << 5))) { /* programming upper bank of flash timed out */ putstr("Lower bank of flash timed out!!"); timeout = 0; break; } oldFlashContents = flashContents; timeout--; } if (timeout <= 0) { putstr("programFlashWord timeout\r\n"); putLabeledWord(" flashAddress=", flashAddress); putLabeledWord(" value=", value); putLabeledWord(" flashContents=", flashContents); putLabeledWord(" oldFlashContents=", oldFlashContents); return(-1); } return 0;}static int amdFlashProgramBlock(unsigned long flashAddress, unsigned long *values, int nbytes){ int nwords = nbytes >> 2; int result = 0; int i; for (i = 0; i < nwords; i++) { result |= amdFlashProgramWord(flashAddress + (i*4), values[i]); if (result) break; } return result;}int amdFlashEraseChip (){ int i; long timeout = FLASH_TIMEOUT; unsigned long flashWordOffset = 0; unsigned long flashContents; unsigned long oldFlashContents; const unsigned long hivalue = 0xFFFFl; /* when chip is erased, this is what we should read */ const unsigned long lovalue = 0xFFFFl; /* when chip is erased, this is what we should read */ flashword[0x555] = doubleword(0xAA); flashword[0x2AA] = doubleword(0x55); flashword[0x555] = doubleword(0x80); flashword[0x555] = doubleword(0xAA); flashword[0x2AA] = doubleword(0x55); flashword[0x555] = doubleword(0x10); while (((flashContents = flashword[flashWordOffset]) != 0xFFFFFFFFL) && (timeout > 0)) { unsigned long hiword = (flashContents >> 16) & 0xFFFFl; unsigned long loword = (flashContents >> 0) & 0xFFFFl; if (0 && (hiword != hivalue) && (hiword & (1 << 5))) { /* programming upper bank of flash timed out */ putstr("Upper bank of flash timed out!!"); break; } if (0 && (loword != lovalue) && (loword & (1 << 5))) { /* programming upper bank of flash timed out */ putstr("Lower bank of flash timed out!!"); break; } oldFlashContents = flashContents; /* to check for toggle bits */ timeout--; } if (timeout <= 0) { putstr("eraseFlashChip timeout\r\n"); putLabeledWord(" flashp=", (dword)(&flashword[flashWordOffset])); putLabeledWord(" flashContents=", flashContents); putLabeledWord(" oldFlashContents=", oldFlashContents); return(-1); } return 0;}/* sectorAddress must be a valid start of sector address. sectors must be erased before they can be programmed! */static int amdFlashEraseSector (unsigned long sectorAddress){ int i; long timeout = FLASH_TIMEOUT; unsigned long flashWordOffset = (sectorAddress&flash_address_mask) >> 2; unsigned long flashContents; unsigned long oldFlashContents; const unsigned long hivalue = 0xFFFFl; /* when sector is erased, this is what we should read */ const unsigned long lovalue = 0xFFFFl; /* when sector is erased, this is what we should read */ for (i = 0; i < nsectors; i++) { if (flashSectors[i] == sectorAddress) break; } if (i >= nsectors) { putLabeledWord("eraseFlashSector: sectorAddress must be start of a sector! address=", sectorAddress); putLabeledWord("nsectors=", nsectors);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -