Features/PC System Flash
This is a proposal for a simple flash emulation on QEMU/KVM.
Command line interface
To enable saving of the flash contents, a -flash a command line parameter would be added. This parameter normally will override the -bios file usage.
-flash path path to filename for saving flash contents
If the flash path does not exist, then the -bios file will be read to initialize the flash contents. If the flash path does exist, then it will be used instead of the -bios file contents.
VM hardware interface
Normal reads
The flash content can be read in 1, 2, 4 or 8 byte sizes like the current read-only bios rom. The read accesses are not required to be aligned.
Programming interface
Aside from normal flash read operations, the flash can be communicated with via special sequences of memory read and write operations.
This interface supports 32-bit aligned 32-bit data operations as well as 64-bit aligned 64-bit operations.
In the following examples, the address 0xfffffffc is used for 32-bit examples, and 0xfffffff8 is used for 64-bit examples. However, any properly aligned address can be used from 0x100000000-sizeof(bios.bin) up through 0xfffffff8 (for 64-bit operations) or 0xfffffffc (for 32-bit operations).
Only 1 flash communication operation can occur at one time. If any flash write occurs in another area of the flash, the the previous operation will be cancelled.
Entering flash communication mode
32-bit mode:
write32(addr=0xfffffffc, data=0x5a5a5a5a) read32(addr=0xfffffffc) => returns 0xa5a5a5a5
64-bit mode:
write64(addr=0xfffffff8, data=0x5a5a5a5a5a5a5a5a) read64(addr=0xfffffff8) => returns 0xa5a5a5a5a5a5a5a5
Program flash
- The flash must be in flash communication mode
32-bit mode:
write32(addr=0xfffffffc, data=0x0) read32(addr=0xfffffffc) => returns current flash contents write32(addr=0xfffffffc, data=new flash contents) read32(addr=0xfffffffc) => returns new flash contents read32(addr=0xfffffffc) => returns new flash contents ^ 0xffffffff
64-bit mode:
write64(addr=0xfffffff8, data=0x0) read64(addr=0xfffffff8) => returns current flash contents write64(addr=0xfffffff8, data=new flash contents) read64(addr=0xfffffff8) => returns new flash contents read64(addr=0xfffffff8) => returns new flash contents ^ 0xffffffffffffffff
- Following a successful program operation, the flash will immediately return to normal read mode.
Flash size read
- The flash must be in flash communication mode
32-bit mode:
write32(addr=0xfffffffc, data=0x1) read32(addr=0xfffffffc) => returns the size of the flash device read32(addr=0xfffffffc) => returns the flash size ^ 0xffffffff
64-bit mode:
write64(addr=0xfffffff8, data=0x1) read64(addr=0xfffffff8) => returns the size of the flash device read64(addr=0xfffffff8) => returns the flash size ^ 0xffffffffffffffff
- Following a flash size read operation, the flash will immediately return to normal read mode.
Interruptions
- If the sequences above are not followed exactly, then the flash device should cancel the operation and immediately enter read mode.
- If a non-aligned write operation or a 1 or 2 byte write occurs to the flash while a flash operation is in progress, then the current operation is immediately cancelled.
- If a properly aligned write operation occurs to an different address or of a different size while another operation is in progress, then the current operation is immediately cancelled. If the write was the proper value to begin entering flash communication mode, then it will be accepted, and the sequence can proceed as a new operation.
Examples
- 32-bit flash write example at address 0xffff0000. Data: old=0x76543210, new=0xfedcba98
write32(addr=0xffff0000, data=0x5a5a5a5a) read32(addr=0xffff0000) => returns 0xa5a5a5a5 write32(addr=0xffff0000, data=0x0) read32(addr=0xffff0000) => returns 0x76543210 write32(addr=0xffff0000, data=0xfedcba98) read32(addr=0xffff0000) => returns 0xfedcba98 read32(addr=0xffff0000) => returns 0x01234567
- 64-bit read flash size example at address 0xffff0000. Flash size=0x100000
write64(addr=0xffff0000, data=0x5a5a5a5a) read64(addr=0xffff0000) => returns 0xa5a5a5a5 write64(addr=0xffff0000, data=0x1) read64(addr=0xffff0000) => returns 0x00100000 read64(addr=0xffff0000) => returns 0xffefffff