PCIe Flash memory mapped BAR

Hello,
this is likely not an interesting question since it deals with ~20 years old equipment.

There is an old legacy system where there is PCIe peripheral conceptually similar to famous at those years Intel EtherExpress card.
The peripheral has flash memory chip of 128 kB. There is very little documentation left for the peripheral.
By looking at it there seems to be a BARn which looks like describing flash memory.
I tried to relate it to the following example
https://github.com/microsoft/Windows-driver-samples/blob/master/general/pcidrv/kmdf/HW/nic_init.c
where it is equivalent to BAR2 but source code does not map that bar as they do not want access flash memory.

Is such a feature a tale from the crypt these days ? Or still usable? If usable do I have correct assumption that if a driver would map that memory to virtual memory in Windows then there would be some magical IP on the peripheral to present flash memory as if it were a normal albeit extremely slow RAM-type device memory ?

Thank you
Sergey

First, some assumptions … you’re working with KMDF and PnP, yes? If that’s the case then you can query the PCI config space using as well as examine the returned resource list in PrepareHardware to see if that BAR even exists. If the PnP OS can’t find it and you don’t see it in the config space then it isn’t going to be there …

Second, I assume that the “flash” memory that you’re talking about is persistent across a cold boot, yes? If it truly is “flash” memory then it’s not going to act like “extremely slow RAM” due to the nature of flash memory writes.

With flash memory when you want to “write” something there needs to be an “erase” cycle first, and most flash from that era (and today) erase in 1MB blocks … so if you want to write address A then you need to erase the whole 1MB block that A resides on (so you first copy the contents of that block, then do the erase, then copy back the old contents with the new data added) … that’s complex and painful and because each vendor has their own registers to toggle for the erase cycle no common libraries or API’s for it … you need to roll your own from the datasheet. That’s also why it’s very unlikely that the card exposes the flash memory as a BAR … how would you be able to write a single byte?

The second thing to consider is that flash memory has a specific amount of erase cycles it’s good for, like the tread on a tire. Once you exceed that number then things start to go bad, and for older flash memory that count was surprisingly low (on the order of thousands of operations). Whenever you are dealing with flash you need to keep that count around and be aware of it

More than likely you’ve got a BAR that contains some registers to access the flash memory, and that’s where I would start looking. I would also see if I could find a datasheet for the flash chip and see what’s possible …

Hello,
thank you for the feedback.

@craig_howard said:
First, some assumptions … you’re working with KMDF and PnP, yes?
yes

If that’s the case then you can query the PCI config space using as well as examine the returned resource list in PrepareHardware to see if that BAR even exists.
yes. I hope so. Except some cases when UEFI may alter this situation by interfering with BARs before stuff is handed over to Windows pci.sys

Second, I assume that the “flash” memory that you’re talking about is persistent across a cold boot, yes?
yes true old school NOR flash chip, 64 kB I believe it is 8-bit parallel
That is why I challenged myself to find out what did Intel mean when exposing similar flash chip in Intel EtherExpress card as BARn.

More than likely you’ve got a BAR that contains some registers to access the flash memory, and that’s where I would start looking.

Maybe, but why would Intel in case of EtherExpress say that the BARn is mapped to flash memory and give 1 MB. That is not needed for a handful of registers to access flash.
Looks to me that they did want to “map” entire flash into OS memory somehow…

I am fully aware that one needs to erase a sector in flash (sets all bytes to FF) before writing to it (set some bits to 0). Yes there must be a controller to talk to that flash chip somewhere … inside ASIC I would assume…

Anyhow, yeah looks like old stuff is not likely to be usable easily. Datasheet… maybe

It maybe possible that Microsoft engineer writing a sample device driver (now in github) for EtherExpress was misled by Intel documentation and misunderstood that BARn is not what it is. I.e. registers instead of flash memory view.

Thanks

If my memory serves, the flash on these ethernet cards was intended for boot from network (PXE).
It contains real mode BIOS extension code.
PCI has provision for “extension ROM” BAR (offset 0x30 in config space), it was that.
More details (perhaps still interesting): https://resources.infosecinstitute.com/topic/pci-expansion-rom/
– pa

1 Like

@Pavel_A said:
If my memory serves, the flash on these ethernet cards was intended for boot from network (PXE).
It contains real mode BIOS extension code.
PCI has provision for “extension ROM” BAR (offset 0x30 in config space), it was that.
More details (perhaps still interesting): https://resources.infosecinstitute.com/topic/pci-expansion-rom/
– pa

Pavel,
I would think that it was that and thought that too, but in the following document
https://www.intel.com/content/dam/doc/manual/8255x-10-100-mbps-ethernet-controller-software-dev-manual.pdf
on page 11 of Chapter 4 the document states that flash memory BAR is separate from expansion ROM (if I read this document correctly)

PCI Configuration Space

Byte Offset (hexadecimal) Byte 3 Byte 2 Byte 1 Byte 0
0 Device ID Vendor ID
4 Status Register Command Register
8 Class Code (200000h) Revision ID
C BIST Header Type Latency Timer Cache Line Size
10 CSR Memory Mapped Base Address Register
14 CSR I/O Mapped Base Address Register
18 Flash Memory Mapped Base Address Register
1C
Reserved
20
24
28
2C Subsystem ID Subsystem Vendor ID
30 Expansion ROM Base Address Register
…

May it be the case that the same NOR flash memory is described twice in PCI configuration space - at 18h as read/write memory and also at 30h as ROM to run as execute in place ?

Thanks,
Sergey

I think we’re past the research and guessing phase and into the “kick the tire” phase … at this point I’d start reading and writing to that register and see if anything “sticks”, then see if it “sticks” past a cold boot, then see if you can overwrite it, then see if you can send a series of bytes to see if you’re dealing with a latch or a gate register, etc. …