ducky.devices.storage module

Persistent storage support.

Several different persistent storages can be attached to a virtual machine, each with its own id. This module provides methods for manipulating their content. Storages operate with blocks of constant, standard size, though this is not a mandatory requirement - storage with different block size, or even with variable block size can be implemented.

Block IO subsystem transfers blocks between storages and VM,

ducky.devices.storage.BIO_BUSY = 16

Data transfer in progress.

ducky.devices.storage.BIO_DMA = 32

Request direct memory access - data will be transfered directly between storage and RAM..

ducky.devices.storage.BIO_ERR = 2

Error happened while performing the operation.

ducky.devices.storage.BIO_RDY = 1

Operation is completed, user can access data and/or request another operation

ducky.devices.storage.BIO_READ = 4

Request data read - transfer data from storage to memory.

ducky.devices.storage.BIO_SRST = 64

Reset BIO.

ducky.devices.storage.BIO_USER = 108

Flags that user can set - others are read-only.

ducky.devices.storage.BIO_WRITE = 8

Request data write - transfer data from memory to storage.

ducky.devices.storage.BLOCK_SIZE = 1024

Size of block, in bytes.

class ducky.devices.storage.BlockIO(machine, name, mmio_address=None, irq=None, *args, **kwargs)[source]

Bases: ducky.devices.Device

_flag_busy()[source]

Signals BIO is running an operation: BIO_BUSY is set, and BIO_RDY is cleared.

_flag_error()[source]

Signals BIO request failed: BIO_ERR is set, and both BIO_RDY and BIO_BUSY are cleared.

_flag_finished()[source]

Signals BIO is ready to accept new request: BIO_RDY is set, and BIO_BUSY is cleared.

If there was an request running, it is finished now. User can queue another request, or access data in case read by the last request.

boot()[source]
buff_to_memory(addr, buff)[source]
static create_from_config(machine, config, section)[source]
halt()[source]
memory_to_buff(addr, length)[source]
read_data()[source]
reset()[source]
select_storage(sid)[source]
status_write(value)[source]

Handles writes to STATUS register. Starts the IO requested when BIO_READ or BIO_WRITE were set.

write_data(value)[source]
class ducky.devices.storage.BlockIOMMIOMemoryPage(device, *args, **kwargs)[source]

Bases: ducky.devices.MMIOMemoryPage

read_u32(offset)[source]
write_u32(offset, value)[source]
class ducky.devices.storage.BlockIOPorts[source]

Bases: enum.IntEnum

MMIO ports, in form of offsets from a base MMIO address.

ADDR = 16

Address of a memory buffer

BLOCK = 8

Block ID

COUNT = 12

Number of blocks

DATA = 20

Data port, for non-DMA access

SID = 4

ID of selected storage device

STATUS = 0

Status port - query BIO status, and submit commands by setting flags

_member_map_ = OrderedDict([('STATUS', <BlockIOPorts.STATUS: 0>), ('SID', <BlockIOPorts.SID: 4>), ('BLOCK', <BlockIOPorts.BLOCK: 8>), ('COUNT', <BlockIOPorts.COUNT: 12>), ('ADDR', <BlockIOPorts.ADDR: 16>), ('DATA', <BlockIOPorts.DATA: 20>)])
_member_names_ = ['STATUS', 'SID', 'BLOCK', 'COUNT', 'ADDR', 'DATA']
_member_type_

alias of int

_value2member_map_ = {0: <BlockIOPorts.STATUS: 0>, 4: <BlockIOPorts.SID: 4>, 8: <BlockIOPorts.BLOCK: 8>, 12: <BlockIOPorts.COUNT: 12>, 16: <BlockIOPorts.ADDR: 16>, 20: <BlockIOPorts.DATA: 20>}
class ducky.devices.storage.FileBackedStorage(machine, name, filepath=None, *args, **kwargs)[source]

Bases: ducky.devices.storage.Storage

Storage that saves its content into a regular file.

_read(cnt)[source]
_write(buff)[source]
boot()[source]
static create_from_config(machine, config, section)[source]
do_read_blocks(start, cnt)[source]
do_write_blocks(start, cnt, buff)[source]
halt()[source]
class ducky.devices.storage.Storage(machine, name, sid=None, size=None, *args, **kwargs)[source]

Bases: ducky.devices.Device

Base class for all block storages.

Parameters:
  • machine (ducky.machine.Machine) – machine storage is attached to.
  • sid (int) – id of storage.
  • size (int) – size of storage, in bytes.
do_read_blocks(start, cnt)[source]

Read one or more blocks from device to internal buffer.

Child classes are supposed to reimplement this particular method.

Parameters:
  • start (u32_t) – index of the first requested block.
  • cnt (u32_t) – number of blocks to read.
do_write_blocks(start, cnt, buff)[source]

Write one or more blocks from internal buffer to device.

Child classes are supposed to reimplement this particular method.

Parameters:
  • start (u32_t) – index of the first requested block.
  • cnt (u32_t) – number of blocks to write.
read_blocks(start, cnt)[source]

Read one or more blocks from device to internal buffer.

Child classes should not reimplement this method, as it provides checks common for (probably) all child classes.

Parameters:
  • start (u32_t) – index of the first requested block.
  • cnt (u32_t) – number of blocks to read.
write_blocks(start, cnt, buff)[source]

Write one or more blocks from internal buffer to device.

Child classes should not reimplement this method, as it provides checks common for (probably) all child classes.

Parameters:
  • start (u32_t) – index of the first requested block.
  • cnt (u32_t) – number of blocks to write.
exception ducky.devices.storage.StorageAccessError[source]

Bases: exceptions.Exception

Base class for storage-related exceptions.