New tool fm10k-flash #1

Merged
DataHoarder merged 5 commits from fm10k-flash into master 2020-12-21 05:11:25 +00:00
8 changed files with 288 additions and 19 deletions
Showing only changes of commit 60f74b671e - Show all commits

3
.gitignore vendored
View file

@ -1,3 +1,4 @@
/fm10k-dump /fm10k-dump
/*.o /fm10k-flash
*.o
/.idea /.idea

25
COPYING Normal file
View file

@ -0,0 +1,25 @@
Copyright (c) 2014 - 2015, Intel Corporation
Copyright (c) 2020, FM10K-Documentation Contributors
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holders nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View file

@ -1,20 +1,25 @@
CC=cc CC=cc
CFLAGS=-Wall -Wno-unknown-warning-option -Wno-packed-bitfield-compat CFLAGS=-ggdb -Og -Wall -Wno-unknown-warning-option -Wno-packed-bitfield-compat
default: all default: all
all: fm10k-dump all: fm10k-dump fm10k-flash
fm10k.o: fm10k.c fm10k.o: src/fm10k.c
$(CC) -c fm10k.c -o fm10k.o $(CFLAGS) $(CC) -c src/fm10k.c -o src/fm10k.o $(CFLAGS)
fm10k-dump.o: fm10k-dump.c fm10k-dump.o: src/fm10k-dump.c
$(CC) -c fm10k-dump.c -o fm10k-dump.o $(CFLAGS) $(CC) -c src/fm10k-dump.c -o src/fm10k-dump.o $(CFLAGS)
fm10k-dump: fm10k-dump.o fm10k.o fm10k-dump: fm10k-dump.o fm10k.o
$(CC) fm10k-dump.o fm10k.o -o fm10k-dump $(CFLAGS) $(CC) src/fm10k-dump.o src/fm10k.o -o fm10k-dump $(CFLAGS)
fm10k-flash.o: src/fm10k-flash.c
$(CC) -c src/fm10k-flash.c -o src/fm10k-flash.o $(CFLAGS)
fm10k-flash: fm10k-flash.o fm10k.o
$(CC) src/fm10k-flash.o src/fm10k.o -o fm10k-flash $(CFLAGS)
clean: clean:
-rm -f fm10k-dump -rm -f fm10k-dump
-rm -f fm10k-dump.o -rm -f fm10k-flash
-rm -f fm10k.o -rm -f src/*.o

View file

@ -1,6 +1,6 @@
# fm10k-dump # fm10k-dump & fm10k-flash
Utility that allows dumping the SPI Flash Non-Volatile Memory of the FM10000 family of cards. Utility that allows dumping/flashing the SPI Flash Non-Volatile Memory of the FM10000 family of cards.
## Requirements ## Requirements
* GCC >= 4.4.0 or clang * GCC >= 4.4.0 or clang
@ -13,13 +13,18 @@ Utility that allows dumping the SPI Flash Non-Volatile Memory of the FM10000 fam
## Compilation ## Compilation
* `$ make clean && make` * `$ make clean && make`
* You can specify whether to use gcc or clang this way: `$ make CC=gcc` / `$ make CC=clang` * You can specify whether to use gcc or clang this way: `$ make CC=gcc` / `$ make CC=clang`
* An executable named `./fm10k-dump` should now exist. * Two executables named `./fm10k-dump` and `./fm10k-flash` should now exist.
## Usage example ## fm10k-dump usage example
* If the chip on the card is known to the tool, it'll set the image size to match. Alternatively it will use the platform minimum of 8Mbit. * If the chip on the card is known to the tool, it'll set the image size to match. Alternatively it will use the platform minimum of 8Mbit.
* `# ./fm10k-dump /dev/uio0 outputImage.bin` * `# ./fm10k-dump /dev/uio0 outputImage.bin`
* You can also force the image/chip size: `# ./fm10k-dump /dev/uio0 outputImage.bin 32` * You can also force the image/chip size: `# ./fm10k-dump /dev/uio0 outputImage.bin 32`
## fm10k-flash usage example
* _fm10k-flash_ requires a backup of the existing image before flashing a new one, for safety measures. Use _fm10k-dump_ to take a backup copy of the current state before flashing.
* `# ./fm10k-dump /dev/uio0 backupImage.bin`
* `# ./fm10k-flash /dev/uio0 inputImage.bin backupImage.bin`
## License ## License
* BSD-3-Clause * BSD-3-Clause
* See [fm10k-dump.c](fm10k-dump.c) header for more information. * See [COPYING](COPYING) for the full license.

View file

@ -2,7 +2,7 @@
* File: fm10k-dump.c * File: fm10k-dump.c
* Creation Date: December 16, 2020 * 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. * 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 * Compile: make fm10k-dump
* Usage: ./fm10k-dump </dev/uio0> <output.bin> [readSizeInMegabits=8] * Usage: ./fm10k-dump </dev/uio0> <output.bin> [readSizeInMegabits=8]
* *
* Copyright (c) 2014 - 2015, Intel Corporation * Copyright (c) 2014 - 2015, Intel Corporation
@ -109,7 +109,7 @@ int main(int argc, char** argv){
uint8_t* value = malloc(bootImageSize); uint8_t* value = malloc(bootImageSize);
uint32_t strideSize = 1024; uint32_t strideSize = 512;
for(uint32_t addr = 0; addr < bootImageSize; addr += strideSize){ for(uint32_t addr = 0; addr < bootImageSize; addr += strideSize){
printf("\rread @ 0x%08x / 0x%08x %d bytes", addr, bootImageSize, strideSize); printf("\rread @ 0x%08x / 0x%08x %d bytes", addr, bootImageSize, strideSize);

232
src/fm10k-flash.c Normal file
View file

@ -0,0 +1,232 @@
/*****************************************************************************
* File: fm10k-flash.c
* Creation Date: December 20, 2020
* Description: Utility to flash Non Volatile Memory on SPI for FM10K devices. Requires FM10K kernel module running with UIO enabled.
* Compile: make fm10k-flash
* Usage: ./fm10k-flash </dev/uio0> <input.bin> <backup.bin>
*
* Copyright (c) 2014 - 2015, Intel Corporation
* Copyright (c) 2020, FM10K-Documentation Contributors
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the copyright holders nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#include "fm10k.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <unistd.h>
#include <fcntl.h>
int main(int argc, char** argv){
int fdUIO;
FILE* fdBackup;
FILE* fdInput;
if(argc < 4){
printf("Usage: %s </dev/uio0> <input.bin> <backup.bin>\n", argv[0]);
return 1;
}
fdInput = fopen(argv[2], "rb");
if(fdInput == NULL){
printf("Could not open %s\n", argv[2]);
return 1;
}
fdBackup = fopen(argv[3], "rb");
if(fdBackup == NULL){
printf("Could not open existing backup %s\n", argv[3]);
return 1;
}
fseek(fdInput , 0, SEEK_END);
uint32_t fileSize = ftell(fdInput);
rewind(fdInput);
fseek(fdBackup , 0, SEEK_END);
uint32_t backupFileSize = ftell(fdBackup);
rewind(fdBackup);
if(backupFileSize < fileSize){
printf("Backup %d is smaller than new image %d\n", backupFileSize, fileSize);
return 1;
}
fdUIO = open(argv[1], O_RDWR);
if(fdUIO <= 0){
printf("Unable to open uio device %s to write NVM\n", argv[1]);
return 1;
}
void* memmapAddr;
memmapAddr = mmap(NULL, FM10K_UIO_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fdUIO, 0);
if (memmapAddr == MAP_FAILED) {
printf("Unable to map uio device %s to write NVM\n", argv[1]);
close(fdUIO);
return 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);
unsigned int mbitsToReadMax = 8;
const KNOWN_FLASH_DEVICE* knownFlashDevice = getKnownFlashFromManufacturerData(manufacturerInfo);
if(knownFlashDevice != NULL){
printf("Device: %s\n", knownFlashDevice->name);
mbitsToReadMax = knownFlashDevice->sizeInMbit;
}else{
printf("Device: Unknown, defaulting max %uMbit size\n", mbitsToReadMax);
}
if(mbitsToReadMax > 1024){
printf("Too many MBit: %u\n", mbitsToReadMax);
return 1;
}
if(mbitsToReadMax == 0){
printf("Too few MBit: %u\n", mbitsToReadMax);
return 1;
}
uint32_t strideSize = 512;
uint32_t bootImageSizeMax = (mbitsToReadMax * 1024 * 1024) / 8;
if(fileSize > bootImageSizeMax){
printf("Image too large: have %d, can write max %d bytes.\n", fileSize, bootImageSizeMax);
return 1;
}else if(fileSize < bootImageSizeMax){
do{
bootImageSizeMax -= strideSize;
} while (fileSize < bootImageSizeMax);
}
uint8_t* value = calloc(bootImageSizeMax, sizeof(uint8_t));
uint8_t* valueBackup = calloc(bootImageSizeMax, sizeof(uint8_t));
uint8_t* valueCheck = calloc(bootImageSizeMax, sizeof(uint8_t));
if(fread(value, 1, bootImageSizeMax, fdInput) != bootImageSizeMax){
printf("Error reading image file.\n");
return 1;
}
if(fread(valueBackup, 1, bootImageSizeMax, fdBackup) != bootImageSizeMax){
printf("Error reading backup image file.\n");
return 1;
}
if(memcmp(value, valueBackup, bootImageSizeMax) == 0){
printf("NOTE: %s and %s have the same bytes.\n", argv[2], argv[3]);
}
for(uint32_t addr = 0; addr < bootImageSizeMax; addr += strideSize){
printf("\rbackup check @ 0x%08x / 0x%08x %d bytes", addr, bootImageSizeMax, strideSize);
if(fm10k_uio_spi_ReadFlash((uintptr_t)memmapAddr, addr, valueCheck + addr, strideSize)){
return 2;
}
}
printf("\n");
if(memcmp(valueBackup, valueCheck, bootImageSizeMax) != 0){
printf("Backup image mismatch! Dump image again.\n");
return 1;
}else{
printf("Backup matches.\n");
}
sleep(1);
for(uint32_t addr = 0; addr < bootImageSizeMax; addr += 4){
if(memcmp(valueBackup + addr, value + addr, 4) != 0){
printf("write @ 0x%08x: 0x%08x => 0x%08x\n", addr, *(uint32_t*)(valueBackup + addr), *(uint32_t*)(value + addr));
if(fm10k_uio_spi_WriteFlash((uintptr_t)memmapAddr, addr, value + addr, 4)){
return 2;
}
}
}
printf("\n");
sleep(1);
for(uint32_t addr = 0; addr < bootImageSizeMax; addr += strideSize){
printf("\rverify check @ 0x%08x / 0x%08x %d bytes", addr, bootImageSizeMax, strideSize);
if(fm10k_uio_spi_ReadFlash((uintptr_t)memmapAddr, addr, valueCheck + addr, strideSize)){
return 2;
}
}
printf("\n");
for(uint32_t addr = 0; addr < bootImageSizeMax; addr += 4){
if(*(uint32_t*)(value + addr) != *(uint32_t*)(valueCheck + addr)){
printf("@0x%08x: 0x%08x != 0x%08x\n", addr, *(uint32_t*)(value + addr), *(uint32_t*)(valueCheck + addr));
}
}
sleep(1);
if(memcmp(value, valueCheck, bootImageSizeMax) != 0){
printf("Data written mismatch! Replacing with backup.\n");
for(uint32_t addr = 0; addr < bootImageSizeMax; addr += strideSize){
printf("\rwrite backup @ 0x%08x / 0x%08x %d bytes", addr, bootImageSizeMax, strideSize);
if(fm10k_uio_spi_WriteFlash((uintptr_t)memmapAddr, addr, valueBackup + addr, strideSize)){
return 2;
}
}
}else{
printf("Data written verified.\n");
}
sleep(1);
free(value);
free(valueBackup);
free(valueCheck);
fclose(fdInput);
fclose(fdBackup);
printf("\nWritten %u bytes\n", bootImageSizeMax);
return 0;
}

View file

@ -280,8 +280,8 @@ uint32_t fm10k_uio_spi_WriteFlash(uintptr_t mem, uint32_t address, const uint8_t
spiCtrl.fields.Enable = 1; spiCtrl.fields.Enable = 1;
/* header: command (1 byte: PAGE_PROGRAM) + address (3 bytes) */ /* header: command (1 byte: READ_MODIFY_WRITE) + address (3 bytes) */
header = (FM10K_SPI_HEADER_COMMAND_PAGE_PROGRAM << 24) | (address & 0xffffff); header = (FM10K_SPI_HEADER_COMMAND_READ_MODIFY_WRITE_512 << 24) | (address & 0xffffff);
WriteRegister32(mem, FM10K_REGISTER_SPI_HEADER, header); WriteRegister32(mem, FM10K_REGISTER_SPI_HEADER, header);
/* first loop only: set send header flag. Following loops: shift only data. */ /* first loop only: set send header flag. Following loops: shift only data. */

View file

@ -49,6 +49,7 @@
#define FM10K_SPI_HEADER_COMMAND_PAGE_PROGRAM 0x02 #define FM10K_SPI_HEADER_COMMAND_PAGE_PROGRAM 0x02
#define FM10K_SPI_HEADER_COMMAND_READ_BYTES 0x03 #define FM10K_SPI_HEADER_COMMAND_READ_BYTES 0x03
#define FM10K_SPI_HEADER_COMMAND_READ_MODIFY_WRITE_512 0x58
#define FM10K_SPI_HEADER_COMMAND_READ_MANUFACTURER_INFORMATION 0x9F #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 */ /* 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 */