fm10k-dump/src/fm10k-dump.c

138 lines
5.2 KiB
C

/*****************************************************************************
* File: fm10k-dump.c
* 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: make fm10k-dump
* Usage: ./fm10k-dump <output.bin> [readSizeInMegabits=8]
*
* Copyright (c) 2014 - 2015, Intel Corporation
* Copyright (c) 2021, 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 <stdlib.h>
int main(int argc, char **argv) {
FILE *fdOutput;
if (argc < 2) {
printf("Usage: %s <output.bin> [forceSizeInMegabits, default 8]\n", argv[0]);
return 1;
}
fdOutput = fopen(argv[1], "wb");
if (fdOutput == NULL) {
printf("Could not create %s\n", argv[1]);
return 1;
}
FM10K_PCI_MAPPED_DEVICE map;
FM10K_PCI_DEVICES devices = fm10k_pci_findDevices();
if(fm10k_pci_findDevice(&devices, &map)){
printf("Unable to find FM10K device with BAR4 port access, or could not take SPI lock. Check bifurcation settings?\n");
return 1;
}
printf("FM10K device found at %s :: Vendor 0x%04x :: Class 0x%04x\n", map.device->bar4Path, map.device->vendor, map.device->class);
SPI_COMMAND_READ_MANUFACTURER_RESULT manufacturerInfo = fm10k_mem_spi_ReadManufacturerData((uintptr_t) map.map);
if (manufacturerInfo.value == 0) {
printf("Error getting manufacturer information\n");
fm10k_mem_ReleasePlatformLock((uintptr_t) map.map);
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 mbitsToRead = 8;
const KNOWN_FLASH_DEVICE *knownFlashDevice = getKnownFlashFromManufacturerData(manufacturerInfo);
if (knownFlashDevice != NULL) {
printf("SPI Device: %s\n", knownFlashDevice->name);
mbitsToRead = knownFlashDevice->sizeInMbit;
} else {
printf("SPI Device: Unknown, defaulting %uMbit size\n", mbitsToRead);
}
if (argc > 2) {
if (mbitsToRead != 8) {
printf("WARNING: %uMbit size was already auto-detected\n", mbitsToRead);
}
mbitsToRead = strtoul(argv[2], NULL, 10);
printf("Forcing %uMbit size\n", mbitsToRead);
}
if (mbitsToRead > 1024) {
printf("Too many MBit: %u\n", mbitsToRead);
fm10k_mem_ReleasePlatformLock((uintptr_t) map.map);
return 1;
}
if (mbitsToRead < 8) {
printf("Too few MBit: %u\n", mbitsToRead);
fm10k_mem_ReleasePlatformLock((uintptr_t) map.map);
return 1;
}
uint32_t bootImageSize = (mbitsToRead * 1024 * 1024) / 8;
uint8_t *value = malloc(bootImageSize);
uint32_t strideSize = 512;
for (uint32_t addr = 0; addr < bootImageSize; addr += strideSize) {
printf("\rread @ 0x%08x / 0x%08x %d bytes", addr, bootImageSize, strideSize);
if (fm10k_mem_spi_ReadFlash((uintptr_t) map.map, addr, value + addr, strideSize)) {
fm10k_mem_ReleasePlatformLock((uintptr_t) map.map);
return 2;
}
}
fwrite(value, 1, bootImageSize, fdOutput);
free(value);
fclose(fdOutput);
printf("\n");
fm10k_mem_ReleasePlatformLock((uintptr_t) map.map);
fm10k_pci_unmapDevice(&map);
printf("Read %u bytes\n", bootImageSize);
return 0;
}