Add support for NBT-based custom HDD items.

In particular, add ones with a named "base" block device, for now just one with the linux root fs.
Using this to replace the hardcoded always present one.
This commit is contained in:
Florian Nücke
2020-12-19 03:01:16 +01:00
parent 64d9939f82
commit 8cafbfc49f
10 changed files with 460 additions and 209 deletions

View File

@@ -1,5 +1,7 @@
package li.cil.oc2;
public final class Config {
public static final long maxAllocatedData = 512 * Constants.MEGABYTE;
public static long maxAllocatedData = 512 * Constants.MEGABYTE;
public static int maxHddSize = 8 * Constants.MEGABYTE;
}

View File

@@ -1,5 +1,7 @@
package li.cil.oc2;
import li.cil.oc2.api.API;
public final class Constants {
public static final int KILOBYTE = 1024;
public static final int MEGABYTE = 1024 * KILOBYTE;
@@ -11,4 +13,9 @@ public final class Constants {
public static final String RAM_NAME = "ram";
public static final String HDD_NAME = "hdd";
public static final String HDD_INFO_NBT_TAG_NAME = API.MOD_ID + "hdd";
public static final String HDD_SIZE_NBT_TAG_NAME = "size";
public static final String HDD_BASE_NBT_TAG_NAME = "base";
public static final String HDD_READONLY_NBT_TAG_NAME = "readonly";
}

View File

@@ -49,7 +49,7 @@ public final class OpenComputers {
public static final RegistryObject<Item> SCREEN_ITEM = ITEMS.register(Constants.SCREEN_BLOCK_NAME, () -> new BlockItem(SCREEN_BLOCK.get(), new Item.Properties().group(ITEM_GROUP)));
public static final RegistryObject<Item> RAM_8M_ITEM = ITEMS.register(Constants.RAM_NAME, () -> new Item(new Item.Properties().group(ITEM_GROUP)));
public static final RegistryObject<Item> HDD_8M_ITEM = ITEMS.register(Constants.HDD_NAME, () -> new Item(new Item.Properties().maxStackSize(1).group(ITEM_GROUP)));
public static final RegistryObject<Item> HDD_ITEM = ITEMS.register(Constants.HDD_NAME, () -> new Item(new Item.Properties().maxStackSize(1).group(ITEM_GROUP)));
public static final DeferredRegister<TileEntityType<?>> TILES = DeferredRegister.create(ForgeRegistries.TILE_ENTITIES, API.MOD_ID);
public static final RegistryObject<TileEntityType<ComputerTileEntity>> COMPUTER_TILE_ENTITY = TILES.register(Constants.COMPUTER_BLOCK_NAME, () -> TileEntityType.Builder.create(ComputerTileEntity::new, COMPUTER_BLOCK.get()).build(null));

View File

@@ -2,6 +2,7 @@ package li.cil.oc2.common.block.entity;
import it.unimi.dsi.fastutil.bytes.ByteArrayFIFOQueue;
import li.cil.ceres.api.Serialized;
import li.cil.oc2.Constants;
import li.cil.oc2.OpenComputers;
import li.cil.oc2.api.bus.DeviceBusElement;
import li.cil.oc2.api.bus.device.Device;
@@ -70,7 +71,7 @@ public final class ComputerTileEntity extends AbstractTileEntity implements ITic
private static final String ITEMS_NBT_TAG_NAME = "items";
private static final int DEVICE_LOAD_RETRY_INTERVAL = 10 * 20; // In ticks.
private static final int VFS_INTERRUPT = 0x5;
private static final int VFS_INTERRUPT = 0x4;
///////////////////////////////////////////////////////////////////
@@ -124,7 +125,11 @@ public final class ComputerTileEntity extends AbstractTileEntity implements ITic
itemHandler.setStackInSlot(1, new ItemStack(OpenComputers.RAM_8M_ITEM.get()));
itemHandler.setStackInSlot(2, new ItemStack(OpenComputers.RAM_8M_ITEM.get()));
itemHandler.setStackInSlot(4, new ItemStack(OpenComputers.HDD_8M_ITEM.get()));
final ItemStack hdd = new ItemStack(OpenComputers.HDD_ITEM.get());
final CompoundNBT hddInfo = new CompoundNBT();
hddInfo.putString(Constants.HDD_BASE_NBT_TAG_NAME, "linux");
hdd.setTagInfo(Constants.HDD_INFO_NBT_TAG_NAME, hddInfo);
itemHandler.setStackInSlot(4, hdd);
}
public Terminal getTerminal() {

View File

@@ -0,0 +1,242 @@
package li.cil.oc2.common.bus.device;
import li.cil.oc2.api.bus.device.vm.*;
import li.cil.oc2.common.bus.device.provider.util.AbstractObjectProxy;
import li.cil.oc2.common.serialization.BlobStorage;
import li.cil.oc2.common.serialization.NBTSerialization;
import li.cil.oc2.common.util.NBTTagIds;
import li.cil.oc2.common.vm.Allocator;
import li.cil.sedna.api.device.BlockDevice;
import li.cil.sedna.device.virtio.VirtIOBlockDevice;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundNBT;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Optional;
import java.util.OptionalInt;
import java.util.OptionalLong;
import java.util.UUID;
public abstract class AbstractHardDiskDriveDevice<T extends BlockDevice> extends AbstractObjectProxy<ItemStack> implements VMDevice, VMDeviceLifecycleListener {
private static final UUID SERIALIZATION_KEY = UUID.fromString("8842cf60-a6e6-44d2-b442-380007625078");
private static final String DEVICE_NBT_TAG_NAME = "device";
private static final String ADDRESS_NBT_TAG_NAME = "address";
private static final String INTERRUPT_NBT_TAG_NAME = "interrupt";
private static final String BLOB_HANDLE_NBT_TAG_NAME = "blob";
///////////////////////////////////////////////////////////////
private final UUID allocHandle = Allocator.createHandle();
private BlobStorage.JobHandle jobHandle;
private T data;
private VirtIOBlockDevice device;
///////////////////////////////////////////////////////////////
// Online persisted data.
private CompoundNBT deviceNbt;
private Long address;
private Integer interrupt;
// Offline persisted data.
private UUID blobHandle;
///////////////////////////////////////////////////////////////
protected AbstractHardDiskDriveDevice(final ItemStack stack) {
super(stack);
}
@Override
public VMDeviceLoadResult load(final VMContext context) {
if (!allocateDevice(context)) {
return VMDeviceLoadResult.fail();
}
if (!claimAddress(context)) {
Allocator.freeMemory(allocHandle);
return VMDeviceLoadResult.fail();
}
if (!claimInterrupt(context)) {
Allocator.freeMemory(allocHandle);
return VMDeviceLoadResult.fail();
}
loadPersistedState();
return VMDeviceLoadResult.success();
}
@Override
public void handleLifecycleEvent(final VMDeviceLifecycleEventType event) {
switch (event) {
case RESUME_RUNNING:
awaitStorageOperation();
break;
case UNLOAD:
unload();
break;
}
}
@Override
public Optional<UUID> getSerializationKey() {
return Optional.of(SERIALIZATION_KEY);
}
@Override
public CompoundNBT serializeNBT() {
final CompoundNBT nbt = new CompoundNBT();
if (data != null) {
final Optional<InputStream> optional = getSerializationStream(data);
optional.ifPresent(stream -> {
blobHandle = BlobStorage.validateHandle(blobHandle);
jobHandle = BlobStorage.submitSave(blobHandle, stream);
});
if (!optional.isPresent()) {
BlobStorage.freeHandle(blobHandle);
blobHandle = null;
}
}
if (device != null) {
deviceNbt = NBTSerialization.serialize(device);
}
if (deviceNbt != null) {
nbt.put(DEVICE_NBT_TAG_NAME, deviceNbt);
}
if (address != null) {
nbt.putLong(ADDRESS_NBT_TAG_NAME, address);
}
if (interrupt != null) {
nbt.putInt(INTERRUPT_NBT_TAG_NAME, interrupt);
}
if (blobHandle != null) {
nbt.putUniqueId(BLOB_HANDLE_NBT_TAG_NAME, blobHandle);
}
return nbt;
}
@Override
public void deserializeNBT(final CompoundNBT nbt) {
if (nbt.hasUniqueId(BLOB_HANDLE_NBT_TAG_NAME)) {
blobHandle = nbt.getUniqueId(BLOB_HANDLE_NBT_TAG_NAME);
}
if (nbt.contains(DEVICE_NBT_TAG_NAME, NBTTagIds.TAG_COMPOUND)) {
deviceNbt = nbt.getCompound(DEVICE_NBT_TAG_NAME);
}
if (nbt.contains(ADDRESS_NBT_TAG_NAME, NBTTagIds.TAG_LONG)) {
address = nbt.getLong(ADDRESS_NBT_TAG_NAME);
}
if (nbt.contains(INTERRUPT_NBT_TAG_NAME, NBTTagIds.TAG_INT)) {
interrupt = nbt.getInt(INTERRUPT_NBT_TAG_NAME);
}
}
///////////////////////////////////////////////////////////////
protected abstract int getSize();
protected abstract T createDevice();
protected abstract Optional<InputStream> getSerializationStream(T device);
protected abstract OutputStream getDeserializationStream(T device);
///////////////////////////////////////////////////////////////
private boolean allocateDevice(final VMContext context) {
if (!Allocator.claimMemory(allocHandle, getSize())) {
return false;
}
data = createDevice();
device = new VirtIOBlockDevice(context.getMemoryMap(), data);
return true;
}
private boolean claimAddress(final VMContext context) {
final OptionalLong claimedAddress;
if (this.address != null) {
claimedAddress = context.getMemoryRangeAllocator().claimMemoryRange(this.address, device);
} else {
claimedAddress = context.getMemoryRangeAllocator().claimMemoryRange(device);
}
if (!claimedAddress.isPresent()) {
return false;
}
this.address = claimedAddress.getAsLong();
return true;
}
private boolean claimInterrupt(final VMContext context) {
final OptionalInt claimedInterrupt;
if (this.interrupt != null) {
claimedInterrupt = context.getInterruptAllocator().claimInterrupt(this.interrupt);
} else {
claimedInterrupt = context.getInterruptAllocator().claimInterrupt();
}
if (!claimedInterrupt.isPresent()) {
return false;
}
this.interrupt = claimedInterrupt.getAsInt();
device.getInterrupt().set(this.interrupt, context.getInterruptController());
return true;
}
private void loadPersistedState() {
if (blobHandle != null) {
jobHandle = BlobStorage.submitLoad(blobHandle, getDeserializationStream(data));
}
if (deviceNbt != null) {
NBTSerialization.deserialize(deviceNbt, device);
}
}
private void awaitStorageOperation() {
if (jobHandle != null) {
jobHandle.await();
jobHandle = null;
}
}
private void unload() {
// Since we cannot serialize the data in a regular serialize call due to the
// actual data being unloaded at that point, but want to permanently persist
// it (it's the contents of the block device) we need to serialize it in the
// unload, too. Don't need to wait for the job, though.
if (data != null) {
final Optional<InputStream> optional = getSerializationStream(data);
optional.ifPresent(stream -> {
blobHandle = BlobStorage.validateHandle(blobHandle);
BlobStorage.submitSave(blobHandle, stream);
});
if (!optional.isPresent()) {
BlobStorage.freeHandle(blobHandle);
blobHandle = null;
}
}
Allocator.freeMemory(allocHandle);
data = null;
device = null;
deviceNbt = null;
address = null;
interrupt = null;
}
}

View File

@@ -0,0 +1,39 @@
package li.cil.oc2.common.bus.device;
import li.cil.sedna.device.block.ByteBufferBlockDevice;
import net.minecraft.item.ItemStack;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Optional;
public final class HardDiskDriveDevice extends AbstractHardDiskDriveDevice<ByteBufferBlockDevice> {
private final int size;
private final boolean readonly;
public HardDiskDriveDevice(final ItemStack stack, final int size, final boolean readonly) {
super(stack);
this.size = size;
this.readonly = readonly;
}
@Override
protected int getSize() {
return size;
}
@Override
protected ByteBufferBlockDevice createDevice() {
return ByteBufferBlockDevice.create(size, readonly);
}
@Override
protected Optional<InputStream> getSerializationStream(final ByteBufferBlockDevice device) {
return Optional.of(device.getInputStream());
}
@Override
protected OutputStream getDeserializationStream(final ByteBufferBlockDevice device) {
return device.getOutputStream();
}
}

View File

@@ -0,0 +1,113 @@
package li.cil.oc2.common.bus.device;
import li.cil.ceres.BinarySerialization;
import li.cil.sedna.api.device.BlockDevice;
import li.cil.sedna.device.block.SparseBlockDevice;
import li.cil.sedna.utils.ByteBufferInputStream;
import net.minecraft.item.ItemStack;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.util.Optional;
public final class SparseHardDiskDriveDevice extends AbstractHardDiskDriveDevice<SparseBlockDevice> {
private final BlockDevice base;
private final boolean readonly;
public SparseHardDiskDriveDevice(final ItemStack stack, final BlockDevice base, final boolean readonly) {
super(stack);
this.base = base;
this.readonly = readonly;
}
@Override
protected int getSize() {
return (int) base.getCapacity();
}
@Override
protected SparseBlockDevice createDevice() {
return new SparseBlockDevice(base, readonly);
}
@Override
protected Optional<InputStream> getSerializationStream(final SparseBlockDevice device) {
if (device.getBlockCount() == 0) {
return Optional.empty();
}
return Optional.of(new SerializationStream(device));
}
@Override
protected OutputStream getDeserializationStream(final SparseBlockDevice device) {
return new DeserializationStream(device);
}
private static final class SerializationStream extends InputStream {
private final SparseBlockDevice device;
private ByteBufferInputStream stream;
private SerializationStream(final SparseBlockDevice device) {
this.device = device;
}
@Override
public int read() {
ensureSerialized();
return stream.read();
}
@Override
public int read(final byte[] b, final int off, final int len) {
ensureSerialized();
return stream.read(b, off, len);
}
@Override
public long skip(final long n) throws IOException {
return stream.skip(n);
}
@Override
public int available() throws IOException {
return stream.available();
}
private void ensureSerialized() {
if (stream != null) {
return;
}
stream = new ByteBufferInputStream(BinarySerialization.serialize(device));
}
}
private static final class DeserializationStream extends OutputStream {
private final SparseBlockDevice device;
private final ByteArrayOutputStream stream;
public DeserializationStream(final SparseBlockDevice device) {
this.device = device;
stream = new ByteArrayOutputStream();
}
@Override
public void write(final int b) {
stream.write(b);
}
@Override
public void write(final byte[] b, final int off, final int len) {
stream.write(b, off, len);
}
@Override
public void close() {
BinarySerialization.deserialize(ByteBuffer.wrap(stream.toByteArray()), device);
}
}
}

View File

@@ -0,0 +1,7 @@
@ParametersAreNonnullByDefault
@MethodsReturnNonnullByDefault
package li.cil.oc2.common.bus.device;
import mcp.MethodsReturnNonnullByDefault;
import javax.annotation.ParametersAreNonnullByDefault;

View File

@@ -1,226 +1,70 @@
package li.cil.oc2.common.bus.device.provider;
import li.cil.oc2.Config;
import li.cil.oc2.Constants;
import li.cil.oc2.OpenComputers;
import li.cil.oc2.api.bus.device.Device;
import li.cil.oc2.api.bus.device.provider.ItemDeviceQuery;
import li.cil.oc2.api.bus.device.vm.*;
import li.cil.oc2.common.bus.device.HardDiskDriveDevice;
import li.cil.oc2.common.bus.device.SparseHardDiskDriveDevice;
import li.cil.oc2.common.bus.device.provider.util.AbstractItemDeviceProvider;
import li.cil.oc2.common.bus.device.provider.util.AbstractObjectProxy;
import li.cil.oc2.common.serialization.BlobStorage;
import li.cil.oc2.common.serialization.NBTSerialization;
import li.cil.oc2.common.util.ByteBufferInputStream;
import li.cil.oc2.common.util.ByteBufferOutputStream;
import li.cil.oc2.common.util.NBTTagIds;
import li.cil.oc2.common.vm.Allocator;
import li.cil.sedna.api.device.BlockDevice;
import li.cil.sedna.buildroot.Buildroot;
import li.cil.sedna.device.block.ByteBufferBlockDevice;
import li.cil.sedna.device.virtio.VirtIOBlockDevice;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundNBT;
import net.minecraftforge.common.util.LazyOptional;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.util.Optional;
import java.util.OptionalInt;
import java.util.OptionalLong;
import java.util.UUID;
import java.io.IOException;
import java.util.Objects;
public class HardDriveItemDeviceProvider extends AbstractItemDeviceProvider {
private static final Logger LOGGER = LogManager.getLogger();
///////////////////////////////////////////////////////////////////
public HardDriveItemDeviceProvider() {
super(OpenComputers.HDD_8M_ITEM.get());
super(OpenComputers.HDD_ITEM.get());
}
///////////////////////////////////////////////////////////////////
@Override
protected LazyOptional<Device> getItemDevice(final ItemDeviceQuery query) {
return LazyOptional.of(() -> new HardDiskDriveDevice(query.getItemStack()));
}
final ItemStack stack = query.getItemStack();
///////////////////////////////////////////////////////////////////
private static final class HardDiskDriveDevice extends AbstractObjectProxy<ItemStack> implements VMDevice, VMDeviceLifecycleListener {
private static final UUID SERIALIZATION_KEY = UUID.fromString("8842cf60-a6e6-44d2-b442-380007625078");
private static final String BLOB_HANDLE_NBT_TAG_NAME = "blob";
private static final String DEVICE_NBT_TAG_NAME = "device";
private static final String ADDRESS_NBT_TAG_NAME = "address";
private static final String INTERRUPT_NBT_TAG_NAME = "interrupt";
final int HDD_SIZE = 2 * Constants.MEGABYTE;
///////////////////////////////////////////////////////////////
private final UUID allocHandle = Allocator.createHandle();
private BlobStorage.JobHandle jobHandle;
private ByteBufferBlockDevice data;
private VirtIOBlockDevice device;
///////////////////////////////////////////////////////////////
private UUID blobHandle;
private CompoundNBT deviceNbt;
private Long address;
private Integer interrupt;
///////////////////////////////////////////////////////////////
public HardDiskDriveDevice(final ItemStack stack) {
super(stack);
final CompoundNBT info = stack.getChildTag(Constants.HDD_INFO_NBT_TAG_NAME);
if (info == null) {
return LazyOptional.empty();
}
@Override
public VMDeviceLoadResult load(final VMContext context) {
if (!allocateDevice(context)) {
return VMDeviceLoadResult.fail();
final boolean readonly = info.getBoolean(Constants.HDD_READONLY_NBT_TAG_NAME);
if (info.contains(Constants.HDD_BASE_NBT_TAG_NAME, NBTTagIds.TAG_STRING)) {
final String baseName = info.getString(Constants.HDD_BASE_NBT_TAG_NAME);
BlockDevice base = null;
// TODO Allow registering additional base file systems?
if (Objects.equals(baseName, "linux")) {
try {
base = ByteBufferBlockDevice.createFromStream(Buildroot.getRootFilesystem(), true);
} catch (final IOException e) {
LOGGER.error(e);
}
}
if (!claimAddress(context)) {
return VMDeviceLoadResult.fail();
if (base != null) {
final BlockDevice baseForClosure = base;
return LazyOptional.of(() -> new SparseHardDiskDriveDevice(stack, baseForClosure, readonly));
}
if (!claimInterrupt(context)) {
return VMDeviceLoadResult.fail();
}
loadPersistedState();
return VMDeviceLoadResult.success();
} else if (info.contains(Constants.HDD_SIZE_NBT_TAG_NAME, NBTTagIds.TAG_INT)) {
final int size = Math.max(0, Math.min(Config.maxHddSize, info.getInt(Constants.HDD_SIZE_NBT_TAG_NAME)));
return LazyOptional.of(() -> new HardDiskDriveDevice(stack, size, readonly));
}
@Override
public void handleLifecycleEvent(final VMDeviceLifecycleEventType event) {
switch (event) {
case RESUME_RUNNING:
awaitStorageOperation();
break;
case UNLOAD:
unload();
break;
}
}
@Override
public Optional<UUID> getSerializationKey() {
return Optional.of(SERIALIZATION_KEY);
}
@Override
public CompoundNBT serializeNBT() {
final CompoundNBT nbt = new CompoundNBT();
if (data != null) {
blobHandle = BlobStorage.validateHandle(blobHandle);
nbt.putUniqueId(BLOB_HANDLE_NBT_TAG_NAME, blobHandle);
jobHandle = BlobStorage.submitSave(blobHandle, new ByteBufferInputStream(data.getView()));
}
if (device != null) {
deviceNbt = NBTSerialization.serialize(device);
nbt.put(DEVICE_NBT_TAG_NAME, deviceNbt);
}
if (address != null) {
nbt.putLong(ADDRESS_NBT_TAG_NAME, address);
}
if (interrupt != null) {
nbt.putInt(INTERRUPT_NBT_TAG_NAME, interrupt);
}
return nbt;
}
@Override
public void deserializeNBT(final CompoundNBT nbt) {
if (nbt.hasUniqueId(BLOB_HANDLE_NBT_TAG_NAME)) {
blobHandle = nbt.getUniqueId(BLOB_HANDLE_NBT_TAG_NAME);
}
if (nbt.contains(DEVICE_NBT_TAG_NAME, NBTTagIds.TAG_COMPOUND)) {
deviceNbt = nbt.getCompound(DEVICE_NBT_TAG_NAME);
}
if (nbt.contains(ADDRESS_NBT_TAG_NAME, NBTTagIds.TAG_LONG)) {
address = nbt.getLong(ADDRESS_NBT_TAG_NAME);
}
if (nbt.contains(INTERRUPT_NBT_TAG_NAME, NBTTagIds.TAG_INT)) {
interrupt = nbt.getInt(INTERRUPT_NBT_TAG_NAME);
}
}
///////////////////////////////////////////////////////////////
private boolean allocateDevice(final VMContext context) {
if (!Allocator.claimMemory(allocHandle, HDD_SIZE)) {
return false;
}
data = ByteBufferBlockDevice.create(HDD_SIZE, false);
device = new VirtIOBlockDevice(context.getMemoryMap(), data);
return true;
}
private boolean claimAddress(final VMContext context) {
final OptionalLong claimedAddress;
if (this.address != null) {
claimedAddress = context.getMemoryRangeAllocator().claimMemoryRange(this.address, device);
} else {
claimedAddress = context.getMemoryRangeAllocator().claimMemoryRange(device);
}
if (!claimedAddress.isPresent()) {
Allocator.freeMemory(allocHandle);
return false;
}
this.address = claimedAddress.getAsLong();
return true;
}
private boolean claimInterrupt(final VMContext context) {
final OptionalInt claimedInterrupt;
if (this.interrupt != null) {
claimedInterrupt = context.getInterruptAllocator().claimInterrupt(this.interrupt);
} else {
claimedInterrupt = context.getInterruptAllocator().claimInterrupt();
}
if (!claimedInterrupt.isPresent()) {
Allocator.freeMemory(allocHandle);
return false;
}
this.interrupt = claimedInterrupt.getAsInt();
device.getInterrupt().set(this.interrupt, context.getInterruptController());
return true;
}
private void loadPersistedState() {
if (blobHandle != null) {
jobHandle = BlobStorage.submitLoad(blobHandle, new ByteBufferOutputStream(data.getView()));
}
if (deviceNbt != null) {
NBTSerialization.deserialize(deviceNbt, device);
}
}
private void awaitStorageOperation() {
if (jobHandle != null) {
jobHandle.await();
jobHandle = null;
}
}
private void unload() {
// Finish saves on unload to ensure future loads will read correct data.
awaitStorageOperation();
Allocator.freeMemory(allocHandle);
data = null;
device = null;
address = null;
interrupt = null;
}
return LazyOptional.empty();
}
}

View File

@@ -11,7 +11,6 @@ import li.cil.sedna.buildroot.Buildroot;
import li.cil.sedna.device.block.ByteBufferBlockDevice;
import li.cil.sedna.device.rtc.GoldfishRTC;
import li.cil.sedna.device.serial.UART16550A;
import li.cil.sedna.device.virtio.VirtIOBlockDevice;
import li.cil.sedna.device.virtio.VirtIOConsoleDevice;
import li.cil.sedna.riscv.R5Board;
import org.apache.logging.log4j.LogManager;
@@ -30,9 +29,8 @@ public final class VirtualMachine {
public static final int ACTUAL_CPU_FREQUENCY = REPORTED_CPU_FREQUENCY * 72;
private static final int UART_INTERRUPT = 0x1;
private static final int HDD_INTERRUPT = 0x2;
private static final int RTC_INTERRUPT = 0x3;
private static final int RPC_INTERRUPT = 0x4;
private static final int RTC_INTERRUPT = 0x2;
private static final int RPC_INTERRUPT = 0x3;
private static final ByteBufferBlockDevice ROOT_FS;
@@ -56,7 +54,6 @@ public final class VirtualMachine {
@Serialized public R5Board board;
@Serialized public VirtualMachineDeviceBusAdapter vmAdapter;
@Serialized public UART16550A uart;
@Serialized public VirtIOBlockDevice hdd;
@Serialized public VirtIOConsoleDevice deviceBusSerialDevice;
@Serialized public RPCAdapter rpcAdapter;
@@ -79,11 +76,6 @@ public final class VirtualMachine {
uart.getInterrupt().set(interrupt, interruptController));
memoryRangeAllocator.claimMemoryRange(uart);
hdd = new VirtIOBlockDevice(board.getMemoryMap(), ROOT_FS);
interruptAllocator.claimInterrupt(HDD_INTERRUPT).ifPresent(interrupt ->
hdd.getInterrupt().set(interrupt, interruptController));
memoryRangeAllocator.claimMemoryRange(hdd);
final GoldfishRTC rtc = new GoldfishRTC(this.rtc);
interruptAllocator.claimInterrupt(RTC_INTERRUPT).ifPresent(interrupt ->
rtc.getInterrupt().set(interrupt, interruptController));
@@ -96,7 +88,7 @@ public final class VirtualMachine {
rpcAdapter = new RPCAdapter(busController, deviceBusSerialDevice);
board.setBootArguments("root=/dev/vda ro");
board.setBootArguments("root=/dev/vda rw");
board.setStandardOutputDevice(uart);
}