Read JEDEC Manufacturer Information to try to auto-detect device type and size of memory, change force read size parameter to megabits
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
parent
5e21afe140
commit
204f437be2
125
fm10k-dump.c
125
fm10k-dump.c
|
@ -3,7 +3,7 @@
|
|||
* Creation Date: December 16, 2020
|
||||
* Description: Utility to dump Non Volatile Memory on SPI for FM10K devices. Requires FM10K kernel module running with UIO enabled.
|
||||
* Compile: gcc -o fm10k-dump fm10k-dump.c
|
||||
* Usage: ./fm10k-dump </dev/uio0> <output.bin> [readSizeInMegabytes=1]
|
||||
* Usage: ./fm10k-dump </dev/uio0> <output.bin> [readSizeInMegabits=8]
|
||||
*
|
||||
* Copyright (c) 2014 - 2015, Intel Corporation
|
||||
* Copyright (c) 2020, FM10K-Documentation Contributors
|
||||
|
@ -54,9 +54,11 @@
|
|||
#define FM10K_SPI_FREQ_KHZ 50000
|
||||
|
||||
#define FM10K_SPI_HEADER_COMMAND_READ_BYTES 0x3
|
||||
#define FM10K_SPI_HEADER_COMMAND_READ_MANUFACTURER_INFORMATION 0x9F
|
||||
|
||||
/* Test for GCC >= 4.4.0, see https://gcc.gnu.org/gcc-4.4/changes.html : Packed bit-fields of type char were not properly bit-packed on many targets prior to GCC 4.4 */
|
||||
#if __GNUC__ > 4 || (__GNUC__ == 4 && (__GNUC_MINOR__ >= 4))
|
||||
|
||||
typedef union {
|
||||
struct {
|
||||
uint16_t Freq : 10; // Actual speed is PCIE_REFCLK/(2*(1+Freq))
|
||||
|
@ -75,6 +77,19 @@ typedef union {
|
|||
} __attribute__((packed)) fields;
|
||||
uint32_t value;
|
||||
} SPI_CTRL;
|
||||
|
||||
typedef union {
|
||||
struct {
|
||||
uint8_t RESERVED : 8;
|
||||
uint8_t productVariant : 5;
|
||||
uint8_t subCode : 3;
|
||||
uint8_t densityCode : 5;
|
||||
uint8_t familyCode : 3;
|
||||
uint8_t manufacturerId : 8;
|
||||
} __attribute__((packed)) fields;
|
||||
uint32_t value;
|
||||
} SPI_COMMAND_READ_MANUFACTURER_RESULT;
|
||||
|
||||
#else
|
||||
#error "Packed bit-fields of type char were not properly bit-packed on many targets prior to GCC 4.4, upgrade to GCC >= 4.4."
|
||||
#endif
|
||||
|
@ -116,8 +131,7 @@ uint32_t get_interval_diff(struct timeval *begin, struct timeval *end) {
|
|||
uint32_t fm10k_uio_spi_SetCtrlReg(uintptr_t mem, SPI_CTRL value){
|
||||
struct timeval startTime;
|
||||
uint8_t isTimeout = 0;
|
||||
SPI_CTRL spiCtrl;
|
||||
spiCtrl.value = 0;
|
||||
SPI_CTRL spiCtrl = {0};
|
||||
|
||||
WriteRegister32(mem, FM10K_REGISTER_SPI_CTRL, value.value);
|
||||
|
||||
|
@ -166,11 +180,67 @@ void fm10k_uio_spi_Disable(uintptr_t mem){
|
|||
WriteRegister32(mem, FM10K_REGISTER_SPI_CTRL, newSpiCtrl.value);
|
||||
}
|
||||
|
||||
|
||||
//Error if result.value is 0x00
|
||||
SPI_COMMAND_READ_MANUFACTURER_RESULT fm10k_uio_spi_ReadManufacturerData(uintptr_t mem){
|
||||
|
||||
SPI_COMMAND_READ_MANUFACTURER_RESULT result = {0};
|
||||
SPI_CTRL currentSpiCtrl;
|
||||
SPI_CTRL spiCtrl = {0};
|
||||
|
||||
uint32_t header;
|
||||
int32_t freq;
|
||||
|
||||
fm10k_uio_spi_Enable(mem);
|
||||
|
||||
|
||||
ReadRegister32(mem, FM10K_REGISTER_SPI_CTRL, ¤tSpiCtrl.value);
|
||||
|
||||
if(FM10K_SPI_FREQ_KHZ > 0){
|
||||
freq = ((100000 / (int)FM10K_SPI_FREQ_KHZ) / 2) - 1;
|
||||
if (freq < 0){
|
||||
freq = 0;
|
||||
}
|
||||
spiCtrl.fields.Freq = freq;
|
||||
}
|
||||
|
||||
spiCtrl.fields.Enable = currentSpiCtrl.fields.Enable;
|
||||
|
||||
/* header: command (1 byte: READ_BYTES) */
|
||||
header = FM10K_SPI_HEADER_COMMAND_READ_MANUFACTURER_INFORMATION;
|
||||
WriteRegister32(mem, FM10K_REGISTER_SPI_HEADER, header);
|
||||
|
||||
/* first loop only: set send header flag. Following loops: shift only data. */
|
||||
spiCtrl.fields.Command |= 0b0001;
|
||||
spiCtrl.fields.Command |= 0b0100;
|
||||
spiCtrl.fields.HeaderSize = 1;
|
||||
spiCtrl.fields.DataSize = 4 & 0b11;
|
||||
|
||||
if(fm10k_uio_spi_SetCtrlReg(mem, spiCtrl)){
|
||||
return result;
|
||||
}
|
||||
|
||||
/* get data */
|
||||
ReadRegister32(mem, FM10K_REGISTER_SPI_RX_DATA, &result.value);
|
||||
|
||||
/* release CS */
|
||||
spiCtrl.fields.Command = 0b1000;
|
||||
if(fm10k_uio_spi_SetCtrlReg(mem, spiCtrl)){
|
||||
result.value = 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
fm10k_uio_spi_Disable(mem);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
uint32_t fm10k_uio_spi_ReadFlash(uintptr_t mem, uint32_t address, uint8_t* data, int32_t len){
|
||||
|
||||
SPI_CTRL currentSpiCtrl;
|
||||
SPI_CTRL spiCtrl;
|
||||
spiCtrl.value = 0;
|
||||
SPI_CTRL spiCtrl = {0};
|
||||
|
||||
uint32_t rxData;
|
||||
uint32_t header;
|
||||
|
@ -242,7 +312,7 @@ int main(int argc, char** argv){
|
|||
FILE* fdOutput;
|
||||
|
||||
if(argc < 3){
|
||||
printf("Usage: %s </dev/uio0> <output.bin> [sizeInMB, default 1]\n", argv[0]);
|
||||
printf("Usage: %s </dev/uio0> <output.bin> [forceSizeInMegabits, default 8]\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -266,26 +336,53 @@ int main(int argc, char** argv){
|
|||
return 1;
|
||||
}
|
||||
|
||||
unsigned int mbToRead = 1;
|
||||
SPI_COMMAND_READ_MANUFACTURER_RESULT manufacturerInfo = fm10k_uio_spi_ReadManufacturerData((uintptr_t)memmapAddr);
|
||||
if(manufacturerInfo.value == 0){
|
||||
printf("Error getting manufacturer information\n");
|
||||
return 1;
|
||||
}
|
||||
printf("Manufacturer Info 0x%08x :: JEDEC Manufacturer ID 0x%02x family 0x%02x density 0x%02x %02x:%02x\n", manufacturerInfo.value, manufacturerInfo.fields.manufacturerId, manufacturerInfo.fields.familyCode, manufacturerInfo.fields.densityCode, manufacturerInfo.fields.subCode, manufacturerInfo.fields.productVariant);
|
||||
|
||||
if(argc > 3){
|
||||
mbToRead = strtoul(argv[3], NULL, 10);
|
||||
unsigned int mbitsToRead = 8;
|
||||
|
||||
|
||||
switch (manufacturerInfo.value >> 8) {
|
||||
case 0x1f2701:
|
||||
printf("Device: Adesto AT45Dxxx Standard:1 32Mbit\n");
|
||||
mbitsToRead = 32;
|
||||
break;
|
||||
default:
|
||||
printf("Device: Unknown, defaulting %uMbit size\n", mbitsToRead);
|
||||
break;
|
||||
}
|
||||
|
||||
if(mbToRead > 128){
|
||||
printf("Too many MB: %u\n", mbToRead);
|
||||
if(argc > 3){
|
||||
if(mbitsToRead != 8){
|
||||
printf("WARNING: %uMbit size was already auto-detected\n", mbitsToRead);
|
||||
}
|
||||
mbitsToRead = strtoul(argv[3], NULL, 10);
|
||||
printf("Forcing %uMbit size\n", mbitsToRead);
|
||||
}
|
||||
|
||||
if(mbitsToRead > 1024){
|
||||
printf("Too many MBit: %u\n", mbitsToRead);
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint32_t bootImageSize = mbToRead * 1024 * 1024;
|
||||
if(mbitsToRead < 8){
|
||||
printf("Too few MBit: %u\n", mbitsToRead);
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint32_t bootImageSize = (mbitsToRead * 1024 * 1024) / 8;
|
||||
|
||||
uint8_t* value = malloc(bootImageSize);
|
||||
|
||||
uint32_t strideSize = 1024;
|
||||
|
||||
for(uint32_t addr = 0; addr < bootImageSize; addr += strideSize){
|
||||
printf("\rLOC 0x%08x MAX 0x%08x", addr, bootImageSize);
|
||||
if(fm10k_uio_spi_ReadFlash((uintptr_t)(uint32_t *)memmapAddr, addr, value + addr, strideSize)){
|
||||
printf("\rread @ 0x%08x / 0x%08x %d bytes", addr, bootImageSize, strideSize);
|
||||
if(fm10k_uio_spi_ReadFlash((uintptr_t)memmapAddr, addr, value + addr, strideSize)){
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue