📄 flash.c
字号:
#endif /* !SIMULATOR */ /* manufacturer & device type, then lower and upper boot blocks locks. */ id = (flash_read_byte (base) << 8) | flash_read_byte (base + width); *pid = id; /* ** Try and match id against known devices */ while (notFound && (j < NUMBER_FLASH_TYPES)) { if ((id) == flashTypes [j].id) { notFound = FALSE; } else { j++; } } /* ** Ensure that the id found, if any, is appropriate to the device. */ if (notFound || ((width == 1) && flashTypes [j].is16Bit) || ((width == 2) && !flashTypes [j].is16Bit)) { notFound = TRUE; width *= 2; j = 0; } } while (notFound && (width <= 2)); /* ** If not found set return code */ if (notFound) { id = UNKNOWN_CHIP_ID; j = NUMBER_FLASH_TYPES; } *protectMask = 0;#ifndef SIMULATOR /* ** Protection depends upon chip type. */ switch (id) {#ifndef FLASH_NO_ATMEL_SUPPORT case AT29C040_CHIP_ID: case AT29C040A_CHIP_ID: case W29C040_CHIP_ID: /* The data book says ffff2 for the upper boot block lock, however */ /* ATMEL, when rung, say it should be 7fff2. */ if (flash_read_byte(base + 0x00002) == 0xff) { /* Lower */ *protectMask |= 1; } if (flash_read_byte(base + 0x7fff2) == 0xff) { /* Upper */ *protectMask |= 2; } /* Exit from product identification mode (return to normal operation) */ flash_write_byte(0xaa, 0x5555 + base); flash_write_byte(0x55, 0x2aaa + base); flash_write_byte(0xf0, 0x5555 + base); break;#endif#ifndef FLASH_NO_AMD_SUPPORT case AM29LV017B_CHIP_ID: case AM29LV081B_CHIP_ID: case AM29F040_CHIP_ID: case AM29LV116BB_CHIP_ID: case AM29LV116BT_CHIP_ID: case AM29LV040B_CHIP_ID: case M29W008T_CHIP_ID: case M29W008B_CHIP_ID: case M29W040B_CHIP_ID: case BM29F040_CHIP_ID: case MX29F040_CHIP_ID: case EN29F040_CHIP_ID: case AC29F040_CHIP_ID: case MX29F800B_CHIP_ID: case M29W800AT_CHIP_ID: case M29W800AB_CHIP_ID: case AM29LV800BT_CHIP_ID: case AM29LV800BB_CHIP_ID: case AM29LV160BT_CHIP_ID: case AM29LV160BB_CHIP_ID: case AT49BV1614_CHIP_ID: /* ** AMD chips have hardware protection on sectors this cannot be ** removed by software command. */ { U32 i; U32 s; U32 sector = 0; for (s = 0; s < NUMBER_DIFFERENT_SECTOR_SIZES; s++) { for (i = 0; i < flashTypes [j].sectors [s].numberSectors; i++) { /* ** Returns 0 for unprotected, 1 for protected */ *protectMask |= (flash_read_byte(base + sector + 0x00002 * width) << i); sector += flashTypes [j].sectors [s].size; } } } /* Exit from product identification mode (return to normal operation) */ flash_write_byte(0xaa, 0x5555 * width + base); flash_write_byte(0x55, 0x2aaa * width + base + width - 1); flash_write_byte(0xf0, 0x5555 * width + base); break;#endif#ifndef FLASH_NO_INTEL_SUPPORT case MT28F008B3B_CHIP_ID: case MT28F008B3T_CHIP_ID: case INT28F800B5B_CHIP_ID: case INT28F320J5_CHIP_ID: case LH28F160BVE_CHIP_ID: /* No software readable protection */ /* Exit from product identification mode (return to normal operation) */ flash_write_byte(0xff, base); break;#endif#ifndef FLASH_NO_INTEL_SUPPORT case MX29L1611B_CHIP_ID: assert (flashTypes [j].is16Bit); /* Exit from product identification mode (return to normal operation) */ flash_write_byte(0xaa, 0xAAAA + base); flash_write_byte(0x55, 0x5555 + base); flash_write_byte(0xf0, 0xAAAA + base); break;#endif#ifndef FLASH_NO_SST_SUPPORT case SST28SF040A_CHIP_ID: /* Exit from product identification mode (return to normal operation) */ flash_write_byte(0xff, 0x5555 + base); /* Remove software protection */ flash_read_byte (base + 0x1823); flash_read_byte (base + 0x1820); flash_read_byte (base + 0x1822); flash_read_byte (base + 0x0418); flash_read_byte (base + 0x041b); flash_read_byte (base + 0x0419); flash_read_byte (base + 0x041a); break; #endif case SST39VF080Q_CHIP_ID: case SST39VF016Q_CHIP_ID: /* Exit from product identification mode (return to normal operation) */ flash_write_byte(0xaa, 0x5555 + base); flash_write_byte(0x55, 0x2aaa + base); flash_write_byte(0xf0, 0x5555 + base); break; default: /* Exit from product identification mode (return to normal operation) */ flash_write_byte(0xaa, 0x5555 + base); flash_write_byte(0x55, 0x2aaa + base); flash_write_byte(0xf0, 0x5555 + base); break; } timer_us_wait(10000); /* Spin for 10ms, don't want to be interrupted */#else /* SIMULATOR */ simulator_flash_change_mode(device, read_mode);#endif /* !SIMULATOR */ atmos_endfiqcritical(crit); TRACE3("%C: device %d ID read: %04x protection: %0x %slocked\n", device, id, *protectMask, (*protectMask != 0) ? "" : "un"); return j;} /* read_chip_id_info8 *//*** Name: read_chip_id_info**** Purpose: Read FLASH chip ID from specified device**** This function is called by the console 'id' command and allows the user to** find out what type of FLASH devices are installed in the system.**** Arguments:** chip Device number (starting from 0)** pid Device id value (16 bit)** protectMask Which sectors are protected (bit set indicates a protected sector)**** Result:** index Into internal table***/static U32 read_chip_id_info(U32 device, U32 *pid, U32 *protectMask){ if (flashDevices[device].Is16 == 1) { return read_chip_id_info16(device, pid, protectMask); } else { return read_chip_id_info8(device, pid, protectMask); }}/*** Name: flash_identify_chips**** Determine what type of chips are installed in the system.**** Result:** ESUCCESS All chips identified.** ENOTFOUND Unable to identify a chip. */int flash_identify_chips (void){ U32 protectMask; U32 device; U32 id; int rc = ESUCCESS; assert (initialised); /* loop round checking all chips ... */ for (device = 0; device < NUM_FLASH_DEVICES; device++) { /* find what type of device(s) we have in the system. */ U32 j = read_chip_id_info (device, &id, &protectMask); if (NUMBER_FLASH_TYPES == j) { printf("%C: FLASH device %d unknown (id: %x)\n", device, id); rc = ENOTFOUND; } else if (flashTypes [j].size != flashDevices [device].size) { /* Configuration error */ printf ("%C: FLASH device %d incorrect size configured\n", device); rc = EIO; } else { actualFlashTypes [device].typeIndex = j; actualFlashTypes [device].writeMask = protectMask; } } /* check each device */ /* mark the chips as read, possibly not for the first time */ flashChipsChecked = TRUE; flashChipsBad = (rc != ESUCCESS); return rc;}/*** Name: flash_find_sector_size**** Purpose: Determine the size of a (FLASH) sector at the specified offset within the device**** Arguments:** typeIndex Index into table of device types.** chipOffset Offset within the device.**** Result:** 0 Illegal offset** <>0 Sector size.*/static U32 flash_find_sector_size (U32 typeIndex, U32 chipOffset, U32 *sectorStartOffset){ U32 i; U32 sectorSize; U32 sectorStart; const FlashType * deviceType; assert (typeIndex < NUMBER_FLASH_TYPES); assert (chipOffset < flashTypes [typeIndex].size); deviceType = &flashTypes [typeIndex]; i = 0; sectorSize = 0; sectorStart = 0; while ((0 == sectorSize) && (i < NUMBER_DIFFERENT_SECTOR_SIZES) && (deviceType->sectors [i].size != 0)) { if (chipOffset >= (deviceType->sectors [i].size * deviceType->sectors [i].numberSectors)) { sectorStart += deviceType->sectors [i].size * deviceType->sectors [i].numberSectors; chipOffset -= deviceType->sectors [i].size * deviceType->sectors [i].numberSectors; i++; } else { sectorStart += deviceType->sectors [i].size * (chipOffset / deviceType->sectors [i].size); sectorSize = deviceType->sectors [i].size; } } assert (0 != sectorSize); /* Can't happen. */ if (NULL != sectorStartOffset) { *sectorStartOffset = sectorStart; } return sectorSize;}/*** A small enhancement allows AMD devices to be** programmed if the 'write more zeros' is appropriate. This is useful** when writing the checksum word after an update - it saves 1 sector program** and ditto when re-writing the 'volroot' stucture if it didn't change.*/static int overwrite_flash_bytes (BYTE **srcp, U32 *dstp, U32 *nump){ int rc = ESUCCESS; U32 device = FLASH_DEVICE(*dstp); U32 typeIndex = actualFlashTypes [device].typeIndex; /* Does the chip support individual writes? */ if (NULL != flashTypes [typeIndex].program_byte) { int (*byte_program) (U32 logicalAddress, BYTE value) = flashTypes [typeIndex].program_byte; /* arbitary length check - if not many bytes to program ... */ if (*nump < SMALL_WRITE_LIMIT) /* header structs etc. are smaller than this */ { /* loop while bytes to program checking for "write more */ /* zero's" type operation with AMD. Decrement number and */ /* increment source & destination pointers. */ for (; *nump != 0; (*nump)--, (*srcp)++, (*dstp)++) { /* if the byte is the same - don't program it */ if (flash_read_byte(*dstp) == **srcp) { continue; } /* check if new byte has any 1's where there are 0's */ /* if so, we can't make 0->1 without erase, give up */ else if (~flash_read_byte(*dstp) & **srcp) { break; } /* program the byte, check return code */ else if ((rc = byte_program (*dstp, **srcp)) != ESUCCESS) { return rc; } } /* program 'write more zeros' a byte at a time */ /* see if we were able to program all the bytes ? */ if (*nump == 0) { /* all done, return */ return rc; } } /* small amount of data to program */ /* too much data for byte program OR write more 0's not applicable. */ } return rc;}/*** Gets a new secto
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -