Compare commits
7 commits
Author | SHA1 | Date | |
---|---|---|---|
DataHoarder | 37b1644120 | ||
DataHoarder | 702209cbe6 | ||
DataHoarder | 88646eb2bb | ||
DataHoarder | f13923f5da | ||
DataHoarder | ab1bffe446 | ||
DataHoarder | 3a434aa9c6 | ||
DataHoarder | a361926b62 |
|
@ -57,9 +57,10 @@ local XbpsPipeline(image, version, arch, extra="", gccExtra="gcc", clangExtra="c
|
|||
|
||||
AptPipeline("ubuntu", "18.04", "amd64"),
|
||||
|
||||
AptPipeline("debian", "bullseye", "amd64"),
|
||||
AptPipeline("debian", "bullseye", "arm64"),
|
||||
|
||||
AptPipeline("debian", "buster", "amd64"),
|
||||
AptPipeline("debian", "buster", "arm64"),
|
||||
|
||||
AptPipeline("debian", "stretch", "amd64"),
|
||||
|
||||
|
|
2
COPYING
2
COPYING
|
@ -1,5 +1,5 @@
|
|||
Copyright (c) 2014 - 2015, Intel Corporation
|
||||
Copyright (c) 2020, FM10K-Documentation Contributors
|
||||
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:
|
||||
|
|
|
@ -3,10 +3,10 @@
|
|||
* 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 </dev/uio0> <output.bin> [readSizeInMegabits=8]
|
||||
* Usage: ./fm10k-dump <output.bin> [readSizeInMegabits=8]
|
||||
*
|
||||
* Copyright (c) 2014 - 2015, Intel Corporation
|
||||
* Copyright (c) 2020, FM10K-Documentation Contributors
|
||||
* 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:
|
||||
|
@ -35,13 +35,9 @@
|
|||
#include "fm10k.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/mman.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int fdBAR4;
|
||||
FILE *fdOutput;
|
||||
|
||||
if (argc < 2) {
|
||||
|
@ -56,35 +52,20 @@ int main(int argc, char **argv) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
FM10K_PCI_DEVICE device = fm10k_pci_findDevice();
|
||||
FM10K_PCI_MAPPED_DEVICE map;
|
||||
FM10K_PCI_DEVICES devices = fm10k_pci_findDevices();
|
||||
|
||||
if (device.vendor == 0) {
|
||||
printf("Unable to find FM10K device with BAR4 port access. Check bifurcation settings?\n");
|
||||
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;
|
||||
}
|
||||
|
||||
fdBAR4 = open(device.bar4Path, O_RDWR);
|
||||
if (fdBAR4 <= 0) {
|
||||
printf("Unable to open BAR4 resource %s to read NVM\n", device.bar4Path);
|
||||
return 1;
|
||||
}
|
||||
void *memmapAddr;
|
||||
memmapAddr = mmap(NULL, FM10K_BAR4_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fdBAR4, 0);
|
||||
if (memmapAddr == MAP_FAILED) {
|
||||
printf("Unable to map BAR4 resource %s to read NVM\n", device.bar4Path);
|
||||
close(fdBAR4);
|
||||
return 1;
|
||||
}
|
||||
printf("FM10K device found at %s :: Vendor 0x%04x :: Class 0x%04x\n", map.device->bar4Path, map.device->vendor, map.device->class);
|
||||
|
||||
if(fm10k_mem_TakePlatformLock((uintptr_t) memmapAddr)){
|
||||
printf("Error taking SPI Lock\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
SPI_COMMAND_READ_MANUFACTURER_RESULT manufacturerInfo = fm10k_mem_spi_ReadManufacturerData((uintptr_t) memmapAddr);
|
||||
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) memmapAddr);
|
||||
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",
|
||||
|
@ -97,10 +78,10 @@ int main(int argc, char **argv) {
|
|||
const KNOWN_FLASH_DEVICE *knownFlashDevice = getKnownFlashFromManufacturerData(manufacturerInfo);
|
||||
|
||||
if (knownFlashDevice != NULL) {
|
||||
printf("Device: %s\n", knownFlashDevice->name);
|
||||
printf("SPI Device: %s\n", knownFlashDevice->name);
|
||||
mbitsToRead = knownFlashDevice->sizeInMbit;
|
||||
} else {
|
||||
printf("Device: Unknown, defaulting %uMbit size\n", mbitsToRead);
|
||||
printf("SPI Device: Unknown, defaulting %uMbit size\n", mbitsToRead);
|
||||
}
|
||||
|
||||
if (argc > 2) {
|
||||
|
@ -113,13 +94,13 @@ int main(int argc, char **argv) {
|
|||
|
||||
if (mbitsToRead > 1024) {
|
||||
printf("Too many MBit: %u\n", mbitsToRead);
|
||||
fm10k_mem_ReleasePlatformLock((uintptr_t) memmapAddr);
|
||||
fm10k_mem_ReleasePlatformLock((uintptr_t) map.map);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (mbitsToRead < 8) {
|
||||
printf("Too few MBit: %u\n", mbitsToRead);
|
||||
fm10k_mem_ReleasePlatformLock((uintptr_t) memmapAddr);
|
||||
fm10k_mem_ReleasePlatformLock((uintptr_t) map.map);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -131,8 +112,8 @@ int main(int argc, char **argv) {
|
|||
|
||||
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) memmapAddr, addr, value + addr, strideSize)) {
|
||||
fm10k_mem_ReleasePlatformLock((uintptr_t) memmapAddr);
|
||||
if (fm10k_mem_spi_ReadFlash((uintptr_t) map.map, addr, value + addr, strideSize)) {
|
||||
fm10k_mem_ReleasePlatformLock((uintptr_t) map.map);
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
@ -146,7 +127,9 @@ int main(int argc, char **argv) {
|
|||
|
||||
printf("\n");
|
||||
|
||||
fm10k_mem_ReleasePlatformLock((uintptr_t) memmapAddr);
|
||||
fm10k_mem_ReleasePlatformLock((uintptr_t) map.map);
|
||||
|
||||
fm10k_pci_unmapDevice(&map);
|
||||
|
||||
printf("Read %u bytes\n", bootImageSize);
|
||||
|
||||
|
|
|
@ -3,10 +3,10 @@
|
|||
* 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>
|
||||
* Usage: ./fm10k-flash <input.bin> <backup.bin>
|
||||
*
|
||||
* Copyright (c) 2014 - 2015, Intel Corporation
|
||||
* Copyright (c) 2020, FM10K-Documentation Contributors
|
||||
* 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:
|
||||
|
@ -36,13 +36,10 @@
|
|||
#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 fdBAR4;
|
||||
FILE *fdBackup;
|
||||
FILE *fdInput;
|
||||
|
||||
|
@ -78,35 +75,20 @@ int main(int argc, char **argv) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
FM10K_PCI_DEVICE device = fm10k_pci_findDevice();
|
||||
FM10K_PCI_MAPPED_DEVICE map;
|
||||
FM10K_PCI_DEVICES devices = fm10k_pci_findDevices();
|
||||
|
||||
if (device.vendor == 0) {
|
||||
printf("Unable to find FM10K device with BAR4 port access. Check bifurcation settings?\n");
|
||||
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;
|
||||
}
|
||||
|
||||
fdBAR4 = open(device.bar4Path, O_RDWR);
|
||||
if (fdBAR4 <= 0) {
|
||||
printf("Unable to open BAR4 resource %s to read NVM\n", device.bar4Path);
|
||||
return 1;
|
||||
}
|
||||
void *memmapAddr;
|
||||
memmapAddr = mmap(NULL, FM10K_BAR4_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fdBAR4, 0);
|
||||
if (memmapAddr == MAP_FAILED) {
|
||||
printf("Unable to map BAR4 resource %s to read NVM\n", device.bar4Path);
|
||||
close(fdBAR4);
|
||||
return 1;
|
||||
}
|
||||
printf("FM10K device found at %s :: Vendor 0x%04x :: Class 0x%04x\n", map.device->bar4Path, map.device->vendor, map.device->class);
|
||||
|
||||
if(fm10k_mem_TakePlatformLock((uintptr_t) memmapAddr)){
|
||||
printf("Error taking SPI Lock\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
SPI_COMMAND_READ_MANUFACTURER_RESULT manufacturerInfo = fm10k_mem_spi_ReadManufacturerData((uintptr_t) memmapAddr);
|
||||
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) memmapAddr);
|
||||
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",
|
||||
|
@ -119,21 +101,21 @@ int main(int argc, char **argv) {
|
|||
const KNOWN_FLASH_DEVICE *knownFlashDevice = getKnownFlashFromManufacturerData(manufacturerInfo);
|
||||
|
||||
if (knownFlashDevice != NULL) {
|
||||
printf("Device: %s\n", knownFlashDevice->name);
|
||||
printf("SPI Device: %s\n", knownFlashDevice->name);
|
||||
mbitsToReadMax = knownFlashDevice->sizeInMbit;
|
||||
} else {
|
||||
printf("Device: Unknown, defaulting max %uMbit size\n", mbitsToReadMax);
|
||||
printf("SPI Device: Unknown, defaulting max %uMbit size\n", mbitsToReadMax);
|
||||
}
|
||||
|
||||
if (mbitsToReadMax > 1024) {
|
||||
printf("Too many MBit: %u\n", mbitsToReadMax);
|
||||
fm10k_mem_ReleasePlatformLock((uintptr_t) memmapAddr);
|
||||
fm10k_mem_ReleasePlatformLock((uintptr_t) map.map);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (mbitsToReadMax == 0) {
|
||||
printf("Too few MBit: %u\n", mbitsToReadMax);
|
||||
fm10k_mem_ReleasePlatformLock((uintptr_t) memmapAddr);
|
||||
fm10k_mem_ReleasePlatformLock((uintptr_t) map.map);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -142,7 +124,7 @@ int main(int argc, char **argv) {
|
|||
|
||||
if (fileSize > bootImageSizeMax) {
|
||||
printf("Image too large: have %d, can write max %d bytes.\n", fileSize, bootImageSizeMax);
|
||||
fm10k_mem_ReleasePlatformLock((uintptr_t) memmapAddr);
|
||||
fm10k_mem_ReleasePlatformLock((uintptr_t) map.map);
|
||||
return 1;
|
||||
} else if (fileSize < bootImageSizeMax) {
|
||||
do {
|
||||
|
@ -156,13 +138,13 @@ int main(int argc, char **argv) {
|
|||
|
||||
if (fread(value, 1, bootImageSizeMax, fdInput) != bootImageSizeMax) {
|
||||
printf("Error reading image file.\n");
|
||||
fm10k_mem_ReleasePlatformLock((uintptr_t) memmapAddr);
|
||||
fm10k_mem_ReleasePlatformLock((uintptr_t) map.map);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (fread(valueBackup, 1, bootImageSizeMax, fdBackup) != bootImageSizeMax) {
|
||||
printf("Error reading backup image file.\n");
|
||||
fm10k_mem_ReleasePlatformLock((uintptr_t) memmapAddr);
|
||||
fm10k_mem_ReleasePlatformLock((uintptr_t) map.map);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -173,8 +155,8 @@ int main(int argc, char **argv) {
|
|||
|
||||
for (uint32_t addr = 0; addr < bootImageSizeMax; addr += strideSize) {
|
||||
printf("\rbackup check @ 0x%08x / 0x%08x %d bytes", addr, bootImageSizeMax, strideSize);
|
||||
if (fm10k_mem_spi_ReadFlash((uintptr_t) memmapAddr, addr, valueCheck + addr, strideSize)) {
|
||||
fm10k_mem_ReleasePlatformLock((uintptr_t) memmapAddr);
|
||||
if (fm10k_mem_spi_ReadFlash((uintptr_t) map.map, addr, valueCheck + addr, strideSize)) {
|
||||
fm10k_mem_ReleasePlatformLock((uintptr_t) map.map);
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
@ -183,7 +165,7 @@ int main(int argc, char **argv) {
|
|||
|
||||
if (memcmp(valueBackup, valueCheck, bootImageSizeMax) != 0) {
|
||||
printf("Backup image mismatch! Dump image again.\n");
|
||||
fm10k_mem_ReleasePlatformLock((uintptr_t) memmapAddr);
|
||||
fm10k_mem_ReleasePlatformLock((uintptr_t) map.map);
|
||||
return 1;
|
||||
} else {
|
||||
printf("Backup matches.\n");
|
||||
|
@ -192,7 +174,7 @@ int main(int argc, char **argv) {
|
|||
sleep(1);
|
||||
|
||||
printf("Disabling sector protection.\n");
|
||||
fm10k_mem_spi_DisableSectorProtection((uintptr_t) memmapAddr);
|
||||
fm10k_mem_spi_DisableSectorProtection((uintptr_t) map.map);
|
||||
|
||||
sleep(1);
|
||||
|
||||
|
@ -200,8 +182,8 @@ int main(int argc, char **argv) {
|
|||
for (uint32_t addr = 0; addr < bootImageSizeMax; addr += strideSize) {
|
||||
if (memcmp(valueBackup + addr, value + addr, strideSize) != 0) {
|
||||
printf("write @ 0x%08x\n", addr);
|
||||
if (fm10k_mem_spi_WriteFlash((uintptr_t) memmapAddr, addr, value + addr, strideSize)) {
|
||||
fm10k_mem_ReleasePlatformLock((uintptr_t) memmapAddr);
|
||||
if (fm10k_mem_spi_WriteFlash((uintptr_t) map.map, addr, value + addr, strideSize)) {
|
||||
fm10k_mem_ReleasePlatformLock((uintptr_t) map.map);
|
||||
return 2;
|
||||
}
|
||||
sleep(1);
|
||||
|
@ -215,8 +197,8 @@ int main(int argc, char **argv) {
|
|||
|
||||
for (uint32_t addr = 0; addr < bootImageSizeMax; addr += strideSize) {
|
||||
printf("\rverify check @ 0x%08x / 0x%08x %d bytes", addr, bootImageSizeMax, strideSize);
|
||||
if (fm10k_mem_spi_ReadFlash((uintptr_t) memmapAddr, addr, valueCheck + addr, strideSize)) {
|
||||
fm10k_mem_ReleasePlatformLock((uintptr_t) memmapAddr);
|
||||
if (fm10k_mem_spi_ReadFlash((uintptr_t) map.map, addr, valueCheck + addr, strideSize)) {
|
||||
fm10k_mem_ReleasePlatformLock((uintptr_t) map.map);
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
@ -238,8 +220,8 @@ int main(int argc, char **argv) {
|
|||
for (uint32_t addr = 0; addr < bootImageSizeMax; addr += strideSize) {
|
||||
if (memcmp(valueBackup + addr, valueCheck + addr, strideSize) != 0) {
|
||||
printf("write backup @ 0x%08x\n", addr);
|
||||
if (fm10k_mem_spi_WriteFlash((uintptr_t) memmapAddr, addr, valueBackup + addr, strideSize)) {
|
||||
fm10k_mem_ReleasePlatformLock((uintptr_t) memmapAddr);
|
||||
if (fm10k_mem_spi_WriteFlash((uintptr_t) map.map, addr, valueBackup + addr, strideSize)) {
|
||||
fm10k_mem_ReleasePlatformLock((uintptr_t) map.map);
|
||||
return 2;
|
||||
}
|
||||
sleep(1);
|
||||
|
@ -253,7 +235,9 @@ int main(int argc, char **argv) {
|
|||
|
||||
printf("\n");
|
||||
|
||||
fm10k_mem_ReleasePlatformLock((uintptr_t) memmapAddr);
|
||||
fm10k_mem_ReleasePlatformLock((uintptr_t) map.map);
|
||||
|
||||
fm10k_pci_unmapDevice(&map);
|
||||
|
||||
|
||||
free(value);
|
||||
|
|
122
src/fm10k.c
122
src/fm10k.c
|
@ -3,7 +3,7 @@
|
|||
* Creation Date: December 20, 2020
|
||||
*
|
||||
* Copyright (c) 2014 - 2015, Intel Corporation
|
||||
* Copyright (c) 2020, FM10K-Documentation Contributors
|
||||
* 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:
|
||||
|
@ -36,6 +36,8 @@
|
|||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <sys/mman.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
KNOWN_FLASH_DEVICE KNOWN_FLASH_DEVICE_LIST[] = {
|
||||
{{0x0101271f}, "Adesto AT45DB321E 32-Mbit", 32}, // Present on Silicom PE3100G2DQiRM-QX4
|
||||
|
@ -44,11 +46,11 @@ KNOWN_FLASH_DEVICE KNOWN_FLASH_DEVICE_LIST[] = {
|
|||
};
|
||||
|
||||
void ReadRegister32(uintptr_t mem, uint32_t addr, uint32_t *value) {
|
||||
*value = *(((uint32_t *) mem) + addr);
|
||||
*value = *(((volatile uint32_t *) mem) + addr);
|
||||
}
|
||||
|
||||
void WriteRegister32(uintptr_t mem, uint32_t addr, uint32_t value) {
|
||||
*(uint32_t volatile *) (((uint32_t *) mem) + addr) = value;
|
||||
*(((volatile uint32_t *) mem) + addr) = value;
|
||||
|
||||
//If returning instantly this will caused missed writes. nanosleep wait of 1 nsec was too much. Busy wait works
|
||||
#pragma GCC diagnostic push
|
||||
|
@ -428,43 +430,43 @@ const KNOWN_FLASH_DEVICE *getKnownFlashFromManufacturerData(SPI_COMMAND_READ_MAN
|
|||
return NULL;
|
||||
}
|
||||
|
||||
uint8_t fm10k_mem_spi_LockTake(uintptr_t mem){
|
||||
uint8_t fm10k_mem_spi_LockTake(uintptr_t mem) {
|
||||
uint32_t maxTries = 64;
|
||||
|
||||
API_SPI_LOCK_STATE spiLock;
|
||||
do{
|
||||
do {
|
||||
ReadRegister32(mem, FM10K_API_SPI_LOCK_STATE, &spiLock.value);
|
||||
|
||||
if(!spiLock.fields.LockTaken){
|
||||
if (!spiLock.fields.LockTaken) {
|
||||
spiLock.fields.LockTaken = 1;
|
||||
spiLock.fields.LockOwner = 0; //Switch API
|
||||
WriteRegister32(mem, FM10K_API_SPI_LOCK_STATE, spiLock.value);
|
||||
nanosleep(&(struct timespec){0, 50000}, NULL); //Delay to observe if lock was actually taken by us
|
||||
nanosleep(&(struct timespec) {0, 50000}, NULL); //Delay to observe if lock was actually taken by us
|
||||
ReadRegister32(mem, FM10K_API_SPI_LOCK_STATE, &spiLock.value);
|
||||
if(spiLock.fields.LockTaken && spiLock.fields.LockOwner == 0){
|
||||
if (spiLock.fields.LockTaken && spiLock.fields.LockOwner == 0) {
|
||||
printf("Taken SPI Lock\n");
|
||||
return 0;
|
||||
}
|
||||
}else if(spiLock.fields.LockOwner == 0){ //Are we taking a lock again, with same owner?
|
||||
} else if (spiLock.fields.LockOwner == 0) { //Are we taking a lock again, with same owner?
|
||||
printf("WARNING: SPI Lock was already taken by us, maybe other process was using it?\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
nanosleep(&(struct timespec){0, 1000}, NULL);
|
||||
nanosleep(&(struct timespec) {0, 1000}, NULL);
|
||||
} while (--maxTries);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void fm10k_mem_spi_LockRelease(uintptr_t mem){
|
||||
void fm10k_mem_spi_LockRelease(uintptr_t mem) {
|
||||
API_SPI_LOCK_STATE spiLock;
|
||||
ReadRegister32(mem, FM10K_API_SPI_LOCK_STATE, &spiLock.value);
|
||||
|
||||
if(!spiLock.fields.LockTaken) {
|
||||
if (!spiLock.fields.LockTaken) {
|
||||
printf("WARNING: SPI Lock was already released\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if(spiLock.fields.LockOwner != 0){
|
||||
if (spiLock.fields.LockOwner != 0) {
|
||||
printf("WARNING: SPI Lock Owner unexpected: %u\n", spiLock.fields.LockOwner);
|
||||
return;
|
||||
}
|
||||
|
@ -477,7 +479,7 @@ void fm10k_mem_spi_LockRelease(uintptr_t mem){
|
|||
|
||||
uint32_t bsm_interruptMask[2] = {0, 0};
|
||||
|
||||
void fm10k_mem_bsm_DisableInterrupts(uintptr_t mem){
|
||||
void fm10k_mem_bsm_DisableInterrupts(uintptr_t mem) {
|
||||
//Save old registers
|
||||
ReadRegister32(mem, FM10K_REGISTER_INTERRUPT_MASK_BSM(0), bsm_interruptMask);
|
||||
ReadRegister32(mem, FM10K_REGISTER_INTERRUPT_MASK_BSM(1), bsm_interruptMask + 1);
|
||||
|
@ -485,32 +487,94 @@ void fm10k_mem_bsm_DisableInterrupts(uintptr_t mem){
|
|||
WriteRegister32(mem, FM10K_REGISTER_INTERRUPT_MASK_BSM(1), 0xFFFFFFFF);
|
||||
}
|
||||
|
||||
void fm10k_mem_bsm_RestoreInterrupts(uintptr_t mem){
|
||||
void fm10k_mem_bsm_RestoreInterrupts(uintptr_t mem) {
|
||||
WriteRegister32(mem, FM10K_REGISTER_INTERRUPT_MASK_BSM(0), bsm_interruptMask[0]);
|
||||
WriteRegister32(mem, FM10K_REGISTER_INTERRUPT_MASK_BSM(1), bsm_interruptMask[1]);
|
||||
}
|
||||
|
||||
uint8_t fm10k_mem_TakePlatformLock(uintptr_t mem){
|
||||
if(fm10k_mem_spi_LockTake(mem)){
|
||||
uint8_t fm10k_mem_TakePlatformLock(uintptr_t mem) {
|
||||
if (fm10k_mem_spi_LockTake(mem)) {
|
||||
return 1;
|
||||
}
|
||||
fm10k_mem_bsm_DisableInterrupts(mem);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void fm10k_mem_ReleasePlatformLock(uintptr_t mem){
|
||||
void fm10k_mem_ReleasePlatformLock(uintptr_t mem) {
|
||||
fm10k_mem_spi_LockRelease(mem);
|
||||
fm10k_mem_bsm_RestoreInterrupts(mem);
|
||||
}
|
||||
|
||||
FM10K_PCI_DEVICE fm10k_pci_findDevice() {
|
||||
int fm10k_pci_unmapDevice(FM10K_PCI_MAPPED_DEVICE *map) {
|
||||
if (map->map != NULL && map->map != MAP_FAILED) {
|
||||
if (munmap(map->map, FM10K_BAR4_SIZE) != 0) {
|
||||
return 1;
|
||||
}
|
||||
map->map = NULL;
|
||||
}
|
||||
|
||||
if (map->fd > 0) {
|
||||
if (close(map->fd) != 0) {
|
||||
return 1;
|
||||
}
|
||||
map->fd = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int fm10k_pci_mapDevice(const FM10K_PCI_DEVICE *device, FM10K_PCI_MAPPED_DEVICE *map) {
|
||||
int fdBAR4;
|
||||
fdBAR4 = open(device->bar4Path, O_RDWR);
|
||||
if (fdBAR4 <= 0) {
|
||||
printf("Unable to open BAR4 resource %s to read NVM\n", device->bar4Path);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void *memmapAddr;
|
||||
memmapAddr = mmap(NULL, FM10K_BAR4_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fdBAR4, 0);
|
||||
if (memmapAddr == MAP_FAILED) {
|
||||
printf("Unable to map BAR4 resource %s to read NVM\n", device->bar4Path);
|
||||
close(fdBAR4);
|
||||
return 1;
|
||||
}
|
||||
|
||||
map->device = device;
|
||||
map->fd = fdBAR4;
|
||||
map->map = memmapAddr;
|
||||
|
||||
if (fm10k_mem_TakePlatformLock((uintptr_t) map->map)) {
|
||||
//Error taking lock
|
||||
fm10k_pci_unmapDevice(map);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int fm10k_pci_findDevice(const FM10K_PCI_DEVICES *devices, FM10K_PCI_MAPPED_DEVICE *map) {
|
||||
if (devices->count == 0) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < devices->count; ++i) {
|
||||
if (fm10k_pci_mapDevice(&devices->devices[i], map) == 0) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
FM10K_PCI_DEVICES fm10k_pci_findDevices() {
|
||||
DIR *folder;
|
||||
char fileName[PATH_MAX];
|
||||
FM10K_PCI_DEVICE device = {0, 0, ""};
|
||||
FM10K_PCI_DEVICES devices;
|
||||
devices.count = 0;
|
||||
|
||||
folder = opendir("/sys/bus/pci/devices");
|
||||
if (folder == NULL) {
|
||||
return device;
|
||||
return devices;
|
||||
}
|
||||
|
||||
struct dirent *entry;
|
||||
|
@ -524,7 +588,7 @@ FM10K_PCI_DEVICE fm10k_pci_findDevice() {
|
|||
size_t vendorBytesLen;
|
||||
size_t vendorBytesRead = getdelim(&vendorBytesBuffer, &vendorBytesLen, '\0', vendorBytesPointer);
|
||||
if (vendorBytesRead != -1) {
|
||||
int vendor = (int) strtol(vendorBytesBuffer, NULL, 0);
|
||||
unsigned int vendor = (unsigned int) strtoul(vendorBytesBuffer, NULL, 0);
|
||||
|
||||
if (vendor == 0x8086) { //Intel Corporation
|
||||
|
||||
|
@ -536,15 +600,17 @@ FM10K_PCI_DEVICE fm10k_pci_findDevice() {
|
|||
size_t classBytesRead = getdelim(&classBytesBuffer, &classBytesLen, '\0',
|
||||
classBytesPointer);
|
||||
if (classBytesRead != -1) {
|
||||
int class = (int) strtol(classBytesBuffer, NULL, 0);
|
||||
unsigned int class = (unsigned int) strtoul(classBytesBuffer, NULL, 0);
|
||||
|
||||
if (class == 0x15a4 || class == 0x15d0 || class == 0x15d5) { //FM10000 devices
|
||||
sprintf(fileName, "/sys/bus/pci/devices/%s/resource4", entry->d_name);
|
||||
if (access(fileName, F_OK) == 0) {
|
||||
device.vendor = vendor;
|
||||
device.class = class;
|
||||
devices.devices[devices.count].vendor = vendor;
|
||||
devices.devices[devices.count].class = class;
|
||||
|
||||
sprintf(device.bar4Path, "/sys/bus/pci/devices/%s/resource4", entry->d_name);
|
||||
sprintf(devices.devices[devices.count].bar4Path, "/sys/bus/pci/devices/%s/resource4",
|
||||
entry->d_name);
|
||||
++devices.count;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -563,7 +629,7 @@ FM10K_PCI_DEVICE fm10k_pci_findDevice() {
|
|||
fclose(vendorBytesPointer);
|
||||
}
|
||||
|
||||
if (device.vendor != 0) {
|
||||
if (devices.count >= FM10K_PCI_DEVICE_MAX) {
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -572,5 +638,5 @@ FM10K_PCI_DEVICE fm10k_pci_findDevice() {
|
|||
|
||||
closedir(folder);
|
||||
|
||||
return device;
|
||||
return devices;
|
||||
}
|
||||
|
|
97
src/fm10k.h
97
src/fm10k.h
|
@ -3,7 +3,7 @@
|
|||
* Creation Date: December 20, 2020
|
||||
*
|
||||
* Copyright (c) 2014 - 2015, Intel Corporation
|
||||
* Copyright (c) 2020, FM10K-Documentation Contributors
|
||||
* 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:
|
||||
|
@ -68,49 +68,49 @@
|
|||
#endif
|
||||
|
||||
typedef union {
|
||||
uint32_t value;
|
||||
struct {
|
||||
uint8_t LockTaken : 1; //Whether lock is currently taken by anyone
|
||||
uint8_t LockOwner : 2; //Who owns the lock. Switch API = 0, QV tools = 1, Board Manager = 2, RESERVED = 3
|
||||
uint32_t Reserved : 29;
|
||||
} __attribute__((packed)) fields;
|
||||
uint32_t value;
|
||||
struct {
|
||||
uint8_t LockTaken: 1; //Whether lock is currently taken by anyone
|
||||
uint8_t LockOwner: 2; //Who owns the lock. Switch API = 0, QV tools = 1, Board Manager = 2, RESERVED = 3
|
||||
uint32_t Reserved: 29;
|
||||
} __attribute__((packed)) fields;
|
||||
} API_SPI_LOCK_STATE;
|
||||
|
||||
typedef union {
|
||||
uint32_t value;
|
||||
struct {
|
||||
uint16_t Freq: 10; // Actual speed is PCIE_REFCLK/(2*(1+Freq))
|
||||
uint8_t Enable: 1;
|
||||
uint8_t Command: 4; // 0b00 = reset
|
||||
uint8_t HeaderSize: 2; // 0b00 = 4 bytes
|
||||
uint8_t DataSize: 2; // 0b00 = 4 bytes
|
||||
uint8_t DataShiftMethod: 2; // 0b00 = SINGLE, 0b01 = DUAL, 0b10 = QUAD, 0b11 = Reserved
|
||||
uint8_t Busy: 1; // volatile ReadOnly
|
||||
uint8_t Selected: 1; // volatile ReadOnly
|
||||
uint8_t DirIO2: 1; // 0b0 = Input, 0b1 = Output
|
||||
uint8_t DirIO3: 1; // 0b0 = Input, 0b1 = Output
|
||||
uint8_t PinIO2: 1; // volatile ReadWrite
|
||||
uint8_t PinIO3: 1; // volatile ReadWrite
|
||||
uint8_t Reserved: 5;
|
||||
} __attribute__((packed)) fields;
|
||||
uint32_t value;
|
||||
struct {
|
||||
uint16_t Freq: 10; // Actual speed is PCIE_REFCLK/(2*(1+Freq))
|
||||
uint8_t Enable: 1;
|
||||
uint8_t Command: 4; // 0b00 = reset
|
||||
uint8_t HeaderSize: 2; // 0b00 = 4 bytes
|
||||
uint8_t DataSize: 2; // 0b00 = 4 bytes
|
||||
uint8_t DataShiftMethod: 2; // 0b00 = SINGLE, 0b01 = DUAL, 0b10 = QUAD, 0b11 = Reserved
|
||||
uint8_t Busy: 1; // volatile ReadOnly
|
||||
uint8_t Selected: 1; // volatile ReadOnly
|
||||
uint8_t DirIO2: 1; // 0b0 = Input, 0b1 = Output
|
||||
uint8_t DirIO3: 1; // 0b0 = Input, 0b1 = Output
|
||||
uint8_t PinIO2: 1; // volatile ReadWrite
|
||||
uint8_t PinIO3: 1; // volatile ReadWrite
|
||||
uint8_t Reserved: 5;
|
||||
} __attribute__((packed)) fields;
|
||||
} SPI_CTRL;
|
||||
|
||||
typedef union {
|
||||
uint32_t value;
|
||||
struct {
|
||||
uint8_t manufacturerId: 8;
|
||||
uint8_t densityCode: 5;
|
||||
uint8_t familyCode: 3;
|
||||
uint8_t productVariant: 5;
|
||||
uint8_t subCode: 3;
|
||||
uint8_t Reserved: 8;
|
||||
} __attribute__((packed)) fields;
|
||||
uint32_t value;
|
||||
struct {
|
||||
uint8_t manufacturerId: 8;
|
||||
uint8_t densityCode: 5;
|
||||
uint8_t familyCode: 3;
|
||||
uint8_t productVariant: 5;
|
||||
uint8_t subCode: 3;
|
||||
uint8_t Reserved: 8;
|
||||
} __attribute__((packed)) fields;
|
||||
} SPI_COMMAND_READ_MANUFACTURER_RESULT;
|
||||
|
||||
typedef struct {
|
||||
SPI_COMMAND_READ_MANUFACTURER_RESULT data;
|
||||
char name[64];
|
||||
uint32_t sizeInMbit;
|
||||
SPI_COMMAND_READ_MANUFACTURER_RESULT data;
|
||||
char name[64];
|
||||
uint32_t sizeInMbit;
|
||||
} KNOWN_FLASH_DEVICE;
|
||||
|
||||
#if defined(__TINYC__)
|
||||
|
@ -160,11 +160,30 @@ uint32_t fm10k_mem_spi_ReadFlash(uintptr_t mem, uint32_t address, uint8_t *data,
|
|||
|
||||
uint32_t fm10k_mem_spi_WriteFlash(uintptr_t mem, uint32_t address, const uint8_t *data, uint32_t len);
|
||||
|
||||
#define FM10K_PCI_DEVICE_MAX 16
|
||||
|
||||
typedef struct {
|
||||
uint16_t vendor;
|
||||
uint16_t class;
|
||||
char bar4Path[PATH_MAX];
|
||||
uint16_t vendor;
|
||||
uint16_t class;
|
||||
char bar4Path[PATH_MAX];
|
||||
} FM10K_PCI_DEVICE;
|
||||
|
||||
FM10K_PCI_DEVICE fm10k_pci_findDevice();
|
||||
typedef struct {
|
||||
const FM10K_PCI_DEVICE *device;
|
||||
void *map;
|
||||
int fd;
|
||||
} FM10K_PCI_MAPPED_DEVICE;
|
||||
|
||||
typedef struct {
|
||||
uint32_t count;
|
||||
FM10K_PCI_DEVICE devices[FM10K_PCI_DEVICE_MAX];
|
||||
} FM10K_PCI_DEVICES;
|
||||
|
||||
FM10K_PCI_DEVICES fm10k_pci_findDevices();
|
||||
|
||||
int fm10k_pci_findDevice(const FM10K_PCI_DEVICES *devices, FM10K_PCI_MAPPED_DEVICE *map);
|
||||
|
||||
int fm10k_pci_mapDevice(const FM10K_PCI_DEVICE *device, FM10K_PCI_MAPPED_DEVICE *map);
|
||||
|
||||
int fm10k_pci_unmapDevice(FM10K_PCI_MAPPED_DEVICE *map);
|
||||
|
||||
|
|
10
src/test.c
10
src/test.c
|
@ -5,7 +5,7 @@
|
|||
* Compile: make test-bin
|
||||
* Usage: ./test
|
||||
*
|
||||
* Copyright (c) 2020, FM10K-Documentation Contributors
|
||||
* 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:
|
||||
|
@ -41,15 +41,17 @@ int main(int argc, char **argv) {
|
|||
uint32_t testsFailed = 0;
|
||||
{
|
||||
SPI_CTRL s;
|
||||
TEST((uint32_t)sizeof(s.fields), (uint32_t)sizeof(s.value), "SPI_CTRL packed misalignment. size struct %u, size value %u");
|
||||
TEST((uint32_t) sizeof(s.fields), (uint32_t) sizeof(s.value), "SPI_CTRL packed misalignment. size struct %u, size value %u");
|
||||
}
|
||||
{
|
||||
SPI_COMMAND_READ_MANUFACTURER_RESULT s;
|
||||
TEST((uint32_t)sizeof(s.fields), (uint32_t)sizeof(s.value), "SPI_COMMAND_READ_MANUFACTURER_RESULT packed misalignment. size struct %u, size value %u");
|
||||
TEST((uint32_t) sizeof(s.fields), (uint32_t) sizeof(s.value),
|
||||
"SPI_COMMAND_READ_MANUFACTURER_RESULT packed misalignment. size struct %u, size value %u");
|
||||
}
|
||||
{
|
||||
API_SPI_LOCK_STATE s;
|
||||
TEST((uint32_t)sizeof(s.fields), (uint32_t)sizeof(s.value), "API_SPI_LOCK_STATE packed misalignment. size struct %u, size value %u");
|
||||
TEST((uint32_t) sizeof(s.fields), (uint32_t) sizeof(s.value),
|
||||
"API_SPI_LOCK_STATE packed misalignment. size struct %u, size value %u");
|
||||
}
|
||||
|
||||
printf("\nTests run, failed %u/%u\n", testsFailed, tests);
|
||||
|
|
Loading…
Reference in a new issue