@aptre/v86 0.5.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/v86.browser.js +1016 -60
- package/dist/v86.browser.js.map +4 -4
- package/dist/v86.js +1015 -60
- package/dist/v86.js.map +4 -4
- package/lib/9p.ts +4 -4
- package/lib/filesystem.ts +1 -1
- package/package.json +7 -7
- package/src/browser/starter.ts +11 -21
- package/src/const.ts +2 -0
- package/src/cpu.ts +48 -8
- package/src/pci.ts +8 -3
- package/src/ps2.ts +2 -2
- package/src/virtio.ts +10 -18
- package/src/virtio_mem.ts +349 -0
- package/src/virtio_v86fs.ts +873 -0
- package/src/rust/gen/analyzer.rs +0 -3807
- package/src/rust/gen/analyzer0f.rs +0 -3992
- package/src/rust/gen/interpreter.rs +0 -4447
- package/src/rust/gen/interpreter0f.rs +0 -5404
- package/src/rust/gen/jit.rs +0 -5080
- package/src/rust/gen/jit0f.rs +0 -5547
package/dist/v86.browser.js
CHANGED
|
@@ -142,6 +142,7 @@ var V86Starter = (() => {
|
|
|
142
142
|
var FW_CFG_SIGNATURE_QEMU = 1431127377;
|
|
143
143
|
var WASM_TABLE_SIZE = 900;
|
|
144
144
|
var WASM_TABLE_OFFSET = 1024;
|
|
145
|
+
var WASM_PAGE_SIZE = 65536;
|
|
145
146
|
var MIXER_CHANNEL_LEFT = 0;
|
|
146
147
|
var MIXER_CHANNEL_RIGHT = 1;
|
|
147
148
|
var MIXER_CHANNEL_BOTH = 2;
|
|
@@ -5456,17 +5457,18 @@ var V86Starter = (() => {
|
|
|
5456
5457
|
LOG_VIRTIO
|
|
5457
5458
|
);
|
|
5458
5459
|
}
|
|
5459
|
-
if (data & ~this.device_status & VIRTIO_STATUS_DRIVER_OK && this.device_status & VIRTIO_STATUS_DEVICE_NEEDS_RESET) {
|
|
5460
|
-
this.notify_config_changes();
|
|
5461
|
-
}
|
|
5462
5460
|
if (!this.features_ok) {
|
|
5463
5461
|
if (false) {
|
|
5464
5462
|
dbg_log("Removing FEATURES_OK", LOG_VIRTIO);
|
|
5465
5463
|
}
|
|
5466
5464
|
data &= ~VIRTIO_STATUS_FEATURES_OK;
|
|
5467
5465
|
}
|
|
5466
|
+
const prev_status = this.device_status;
|
|
5468
5467
|
this.device_status = data;
|
|
5469
|
-
if (data & ~
|
|
5468
|
+
if (data & ~prev_status & VIRTIO_STATUS_DRIVER_OK) {
|
|
5469
|
+
if (prev_status & VIRTIO_STATUS_DEVICE_NEEDS_RESET) {
|
|
5470
|
+
this.notify_config_changes();
|
|
5471
|
+
}
|
|
5470
5472
|
options.on_driver_ok();
|
|
5471
5473
|
}
|
|
5472
5474
|
}
|
|
@@ -5703,7 +5705,7 @@ var V86Starter = (() => {
|
|
|
5703
5705
|
// Call only within constructor.
|
|
5704
5706
|
init_capabilities(capabilities) {
|
|
5705
5707
|
let cap_next = this.pci_space[52] = 64;
|
|
5706
|
-
let cap_ptr
|
|
5708
|
+
let cap_ptr;
|
|
5707
5709
|
for (const cap of capabilities) {
|
|
5708
5710
|
const cap_len2 = VIRTIO_PCI_CAP_LENGTH + cap.extra.length;
|
|
5709
5711
|
cap_ptr = cap_next;
|
|
@@ -6924,7 +6926,7 @@ var V86Starter = (() => {
|
|
|
6924
6926
|
(out_byte) => {
|
|
6925
6927
|
if ((this.pci_addr[1] & 6) === 2 && (out_byte & 6) === 6) {
|
|
6926
6928
|
dbg_log("CPU reboot via PCI");
|
|
6927
|
-
cpu.
|
|
6929
|
+
cpu.reboot();
|
|
6928
6930
|
return;
|
|
6929
6931
|
}
|
|
6930
6932
|
this.pci_addr[1] = out_byte;
|
|
@@ -7030,6 +7032,7 @@ var V86Starter = (() => {
|
|
|
7030
7032
|
0,
|
|
7031
7033
|
0,
|
|
7032
7034
|
0,
|
|
7035
|
+
0,
|
|
7033
7036
|
PAM0,
|
|
7034
7037
|
0,
|
|
7035
7038
|
0,
|
|
@@ -7342,7 +7345,11 @@ var V86Starter = (() => {
|
|
|
7342
7345
|
dbg_assert(device.pci_space.length >= 64);
|
|
7343
7346
|
dbg_assert(device_id < this.devices.length);
|
|
7344
7347
|
const space = new Int32Array(64);
|
|
7345
|
-
|
|
7348
|
+
const pci_bytes = new Uint8Array(device.pci_space);
|
|
7349
|
+
const aligned_len = pci_bytes.length & ~3;
|
|
7350
|
+
if (aligned_len > 0) {
|
|
7351
|
+
space.set(new Int32Array(pci_bytes.buffer, 0, aligned_len >> 2));
|
|
7352
|
+
}
|
|
7346
7353
|
this.device_spaces[device_id] = space;
|
|
7347
7354
|
this.devices[device_id] = device;
|
|
7348
7355
|
const bar_space = space.slice(4, 10);
|
|
@@ -7993,7 +8000,7 @@ var V86Starter = (() => {
|
|
|
7993
8000
|
break;
|
|
7994
8001
|
case 254:
|
|
7995
8002
|
dbg_log("CPU reboot via PS2");
|
|
7996
|
-
this.cpu.
|
|
8003
|
+
this.cpu.reboot();
|
|
7997
8004
|
break;
|
|
7998
8005
|
default:
|
|
7999
8006
|
dbg_log(
|
|
@@ -15138,12 +15145,930 @@ var V86Starter = (() => {
|
|
|
15138
15145
|
}
|
|
15139
15146
|
};
|
|
15140
15147
|
|
|
15148
|
+
// src/virtio_mem.ts
|
|
15149
|
+
var VIRTIO_MEM_REQ_PLUG = 0;
|
|
15150
|
+
var VIRTIO_MEM_REQ_UNPLUG = 1;
|
|
15151
|
+
var VIRTIO_MEM_REQ_STATE = 3;
|
|
15152
|
+
var VIRTIO_MEM_RESP_ACK = 0;
|
|
15153
|
+
var VIRTIO_MEM_RESP_NACK = 1;
|
|
15154
|
+
var VIRTIO_MEM_RESP_ERROR = 3;
|
|
15155
|
+
var DEFAULT_BLOCK_SIZE = 128 * 1024 * 1024;
|
|
15156
|
+
var VirtioMem = class {
|
|
15157
|
+
bus;
|
|
15158
|
+
cpu;
|
|
15159
|
+
virtio;
|
|
15160
|
+
block_size;
|
|
15161
|
+
region_addr;
|
|
15162
|
+
region_size;
|
|
15163
|
+
usable_region_size;
|
|
15164
|
+
plugged_size;
|
|
15165
|
+
requested_size;
|
|
15166
|
+
constructor(cpu, bus, region_addr, region_size, block_size) {
|
|
15167
|
+
this.bus = bus;
|
|
15168
|
+
this.cpu = cpu;
|
|
15169
|
+
this.block_size = block_size || DEFAULT_BLOCK_SIZE;
|
|
15170
|
+
this.region_addr = region_addr;
|
|
15171
|
+
this.region_size = region_size;
|
|
15172
|
+
this.usable_region_size = region_size;
|
|
15173
|
+
this.plugged_size = 0;
|
|
15174
|
+
this.requested_size = 0;
|
|
15175
|
+
const queues = [{ size_supported: 32, notify_offset: 0 }];
|
|
15176
|
+
this.virtio = new VirtIO(cpu, {
|
|
15177
|
+
name: "virtio-mem",
|
|
15178
|
+
pci_id: 13 << 3,
|
|
15179
|
+
device_id: 4184,
|
|
15180
|
+
subsystem_device_id: 24,
|
|
15181
|
+
common: {
|
|
15182
|
+
initial_port: 59392,
|
|
15183
|
+
queues,
|
|
15184
|
+
features: [VIRTIO_F_VERSION_1],
|
|
15185
|
+
on_driver_ok: () => {
|
|
15186
|
+
dbg_log("virtio-mem setup", LOG_PCI);
|
|
15187
|
+
}
|
|
15188
|
+
},
|
|
15189
|
+
notification: {
|
|
15190
|
+
initial_port: 59648,
|
|
15191
|
+
single_handler: false,
|
|
15192
|
+
handlers: [
|
|
15193
|
+
(queue_id) => {
|
|
15194
|
+
this.handle_request(queue_id);
|
|
15195
|
+
}
|
|
15196
|
+
]
|
|
15197
|
+
},
|
|
15198
|
+
isr_status: {
|
|
15199
|
+
initial_port: 59136
|
|
15200
|
+
},
|
|
15201
|
+
device_specific: {
|
|
15202
|
+
initial_port: 58880,
|
|
15203
|
+
struct: [
|
|
15204
|
+
// block_size low
|
|
15205
|
+
{
|
|
15206
|
+
bytes: 4,
|
|
15207
|
+
name: "block_size_low",
|
|
15208
|
+
read: () => this.block_size >>> 0,
|
|
15209
|
+
write: () => {
|
|
15210
|
+
}
|
|
15211
|
+
},
|
|
15212
|
+
// block_size high
|
|
15213
|
+
{
|
|
15214
|
+
bytes: 4,
|
|
15215
|
+
name: "block_size_high",
|
|
15216
|
+
read: () => 0,
|
|
15217
|
+
write: () => {
|
|
15218
|
+
}
|
|
15219
|
+
},
|
|
15220
|
+
// node_id (u16 padded to u32)
|
|
15221
|
+
{
|
|
15222
|
+
bytes: 2,
|
|
15223
|
+
name: "node_id",
|
|
15224
|
+
read: () => 0,
|
|
15225
|
+
write: () => {
|
|
15226
|
+
}
|
|
15227
|
+
},
|
|
15228
|
+
// padding (6 bytes as 2+4)
|
|
15229
|
+
{
|
|
15230
|
+
bytes: 2,
|
|
15231
|
+
name: "padding0",
|
|
15232
|
+
read: () => 0,
|
|
15233
|
+
write: () => {
|
|
15234
|
+
}
|
|
15235
|
+
},
|
|
15236
|
+
{
|
|
15237
|
+
bytes: 4,
|
|
15238
|
+
name: "padding1",
|
|
15239
|
+
read: () => 0,
|
|
15240
|
+
write: () => {
|
|
15241
|
+
}
|
|
15242
|
+
},
|
|
15243
|
+
// addr low
|
|
15244
|
+
{
|
|
15245
|
+
bytes: 4,
|
|
15246
|
+
name: "addr_low",
|
|
15247
|
+
read: () => this.region_addr >>> 0,
|
|
15248
|
+
write: () => {
|
|
15249
|
+
}
|
|
15250
|
+
},
|
|
15251
|
+
// addr high
|
|
15252
|
+
{
|
|
15253
|
+
bytes: 4,
|
|
15254
|
+
name: "addr_high",
|
|
15255
|
+
read: () => 0,
|
|
15256
|
+
write: () => {
|
|
15257
|
+
}
|
|
15258
|
+
},
|
|
15259
|
+
// region_size low
|
|
15260
|
+
{
|
|
15261
|
+
bytes: 4,
|
|
15262
|
+
name: "region_size_low",
|
|
15263
|
+
read: () => this.region_size >>> 0,
|
|
15264
|
+
write: () => {
|
|
15265
|
+
}
|
|
15266
|
+
},
|
|
15267
|
+
// region_size high
|
|
15268
|
+
{
|
|
15269
|
+
bytes: 4,
|
|
15270
|
+
name: "region_size_high",
|
|
15271
|
+
read: () => 0,
|
|
15272
|
+
write: () => {
|
|
15273
|
+
}
|
|
15274
|
+
},
|
|
15275
|
+
// usable_region_size low
|
|
15276
|
+
{
|
|
15277
|
+
bytes: 4,
|
|
15278
|
+
name: "usable_region_size_low",
|
|
15279
|
+
read: () => this.usable_region_size >>> 0,
|
|
15280
|
+
write: () => {
|
|
15281
|
+
}
|
|
15282
|
+
},
|
|
15283
|
+
// usable_region_size high
|
|
15284
|
+
{
|
|
15285
|
+
bytes: 4,
|
|
15286
|
+
name: "usable_region_size_high",
|
|
15287
|
+
read: () => 0,
|
|
15288
|
+
write: () => {
|
|
15289
|
+
}
|
|
15290
|
+
},
|
|
15291
|
+
// plugged_size low
|
|
15292
|
+
{
|
|
15293
|
+
bytes: 4,
|
|
15294
|
+
name: "plugged_size_low",
|
|
15295
|
+
read: () => this.plugged_size >>> 0,
|
|
15296
|
+
write: () => {
|
|
15297
|
+
}
|
|
15298
|
+
},
|
|
15299
|
+
// plugged_size high
|
|
15300
|
+
{
|
|
15301
|
+
bytes: 4,
|
|
15302
|
+
name: "plugged_size_high",
|
|
15303
|
+
read: () => 0,
|
|
15304
|
+
write: () => {
|
|
15305
|
+
}
|
|
15306
|
+
},
|
|
15307
|
+
// requested_size low
|
|
15308
|
+
{
|
|
15309
|
+
bytes: 4,
|
|
15310
|
+
name: "requested_size_low",
|
|
15311
|
+
read: () => this.requested_size >>> 0,
|
|
15312
|
+
write: () => {
|
|
15313
|
+
}
|
|
15314
|
+
},
|
|
15315
|
+
// requested_size high
|
|
15316
|
+
{
|
|
15317
|
+
bytes: 4,
|
|
15318
|
+
name: "requested_size_high",
|
|
15319
|
+
read: () => 0,
|
|
15320
|
+
write: () => {
|
|
15321
|
+
}
|
|
15322
|
+
}
|
|
15323
|
+
]
|
|
15324
|
+
}
|
|
15325
|
+
});
|
|
15326
|
+
}
|
|
15327
|
+
handle_request(queue_id) {
|
|
15328
|
+
const queue = this.virtio.queues[queue_id];
|
|
15329
|
+
while (queue.has_request()) {
|
|
15330
|
+
const bufchain = queue.pop_request();
|
|
15331
|
+
const request = new Uint8Array(bufchain.length_readable);
|
|
15332
|
+
bufchain.get_next_blob(request);
|
|
15333
|
+
const type = request[0] | request[1] << 8;
|
|
15334
|
+
const resp = new Uint8Array(8);
|
|
15335
|
+
let resp_type = VIRTIO_MEM_RESP_ERROR;
|
|
15336
|
+
switch (type) {
|
|
15337
|
+
case VIRTIO_MEM_REQ_PLUG:
|
|
15338
|
+
resp_type = this.handle_plug(request);
|
|
15339
|
+
break;
|
|
15340
|
+
case VIRTIO_MEM_REQ_UNPLUG:
|
|
15341
|
+
resp_type = VIRTIO_MEM_RESP_NACK;
|
|
15342
|
+
break;
|
|
15343
|
+
case VIRTIO_MEM_REQ_STATE:
|
|
15344
|
+
resp_type = this.handle_state(request, resp);
|
|
15345
|
+
break;
|
|
15346
|
+
default:
|
|
15347
|
+
dbg_log("virtio-mem: unknown request type " + type, LOG_PCI);
|
|
15348
|
+
}
|
|
15349
|
+
resp[0] = resp_type & 255;
|
|
15350
|
+
resp[1] = resp_type >> 8 & 255;
|
|
15351
|
+
bufchain.set_next_blob(resp);
|
|
15352
|
+
queue.push_reply(bufchain);
|
|
15353
|
+
}
|
|
15354
|
+
queue.flush_replies();
|
|
15355
|
+
}
|
|
15356
|
+
handle_plug(request) {
|
|
15357
|
+
const addr = (request[8] | request[9] << 8 | request[10] << 16 | request[11] << 24) >>> 0;
|
|
15358
|
+
const nb_blocks = request[16] | request[17] << 8;
|
|
15359
|
+
const size = nb_blocks * this.block_size;
|
|
15360
|
+
const new_plugged = this.plugged_size + size;
|
|
15361
|
+
if (new_plugged > this.usable_region_size) {
|
|
15362
|
+
return VIRTIO_MEM_RESP_NACK;
|
|
15363
|
+
}
|
|
15364
|
+
const new_memory_size = this.cpu.memory_size[0] + size;
|
|
15365
|
+
this.cpu.resize_memory(new_memory_size);
|
|
15366
|
+
this.cpu.full_clear_tlb();
|
|
15367
|
+
this.plugged_size = new_plugged;
|
|
15368
|
+
dbg_log(
|
|
15369
|
+
"virtio-mem: plugged " + nb_blocks + " blocks at 0x" + addr.toString(16) + " (" + (size >> 20) + "MB)",
|
|
15370
|
+
LOG_PCI
|
|
15371
|
+
);
|
|
15372
|
+
return VIRTIO_MEM_RESP_ACK;
|
|
15373
|
+
}
|
|
15374
|
+
handle_state(request, resp) {
|
|
15375
|
+
const addr = (request[8] | request[9] << 8 | request[10] << 16 | request[11] << 24) >>> 0;
|
|
15376
|
+
const nb_blocks = request[16] | request[17] << 8;
|
|
15377
|
+
const offset = addr - this.region_addr;
|
|
15378
|
+
const end = offset + nb_blocks * this.block_size;
|
|
15379
|
+
const all_plugged = end <= this.plugged_size ? 1 : 0;
|
|
15380
|
+
resp[8] = all_plugged & 255;
|
|
15381
|
+
resp[9] = all_plugged >> 8 & 255;
|
|
15382
|
+
return VIRTIO_MEM_RESP_ACK;
|
|
15383
|
+
}
|
|
15384
|
+
set_requested_size(size) {
|
|
15385
|
+
this.requested_size = size;
|
|
15386
|
+
if (this.virtio.device_status & 4) {
|
|
15387
|
+
this.virtio.notify_config_changes();
|
|
15388
|
+
}
|
|
15389
|
+
}
|
|
15390
|
+
get_state() {
|
|
15391
|
+
const state = [];
|
|
15392
|
+
state[0] = this.virtio;
|
|
15393
|
+
state[1] = this.block_size;
|
|
15394
|
+
state[2] = this.region_addr;
|
|
15395
|
+
state[3] = this.region_size;
|
|
15396
|
+
state[4] = this.usable_region_size;
|
|
15397
|
+
state[5] = this.plugged_size;
|
|
15398
|
+
state[6] = this.requested_size;
|
|
15399
|
+
return state;
|
|
15400
|
+
}
|
|
15401
|
+
set_state(state) {
|
|
15402
|
+
this.virtio.set_state(state[0]);
|
|
15403
|
+
this.block_size = state[1];
|
|
15404
|
+
this.region_addr = state[2];
|
|
15405
|
+
this.region_size = state[3];
|
|
15406
|
+
this.usable_region_size = state[4];
|
|
15407
|
+
this.plugged_size = state[5];
|
|
15408
|
+
this.requested_size = state[6];
|
|
15409
|
+
}
|
|
15410
|
+
};
|
|
15411
|
+
|
|
15412
|
+
// src/virtio_v86fs.ts
|
|
15413
|
+
var V86FS_MSG_MOUNT = 0;
|
|
15414
|
+
var V86FS_MSG_LOOKUP = 1;
|
|
15415
|
+
var V86FS_MSG_GETATTR = 2;
|
|
15416
|
+
var V86FS_MSG_READDIR = 3;
|
|
15417
|
+
var V86FS_MSG_OPEN = 4;
|
|
15418
|
+
var V86FS_MSG_CLOSE = 5;
|
|
15419
|
+
var V86FS_MSG_READ = 6;
|
|
15420
|
+
var V86FS_MSG_CREATE = 7;
|
|
15421
|
+
var V86FS_MSG_WRITE = 8;
|
|
15422
|
+
var V86FS_MSG_MKDIR = 9;
|
|
15423
|
+
var V86FS_MSG_SETATTR = 10;
|
|
15424
|
+
var V86FS_MSG_FSYNC = 11;
|
|
15425
|
+
var V86FS_MSG_UNLINK = 12;
|
|
15426
|
+
var V86FS_MSG_RENAME = 13;
|
|
15427
|
+
var V86FS_MSG_SYMLINK = 14;
|
|
15428
|
+
var V86FS_MSG_READLINK = 15;
|
|
15429
|
+
var V86FS_MSG_STATFS = 16;
|
|
15430
|
+
var V86FS_MSG_INVALIDATE = 32;
|
|
15431
|
+
var V86FS_MSG_INVALIDATE_DIR = 33;
|
|
15432
|
+
var V86FS_MSG_MOUNT_R = 128;
|
|
15433
|
+
var V86FS_MSG_LOOKUP_R = 129;
|
|
15434
|
+
var V86FS_MSG_GETATTR_R = 130;
|
|
15435
|
+
var V86FS_MSG_READDIR_R = 131;
|
|
15436
|
+
var V86FS_MSG_OPEN_R = 132;
|
|
15437
|
+
var V86FS_MSG_CLOSE_R = 133;
|
|
15438
|
+
var V86FS_MSG_READ_R = 134;
|
|
15439
|
+
var V86FS_MSG_CREATE_R = 135;
|
|
15440
|
+
var V86FS_MSG_WRITE_R = 136;
|
|
15441
|
+
var V86FS_MSG_MKDIR_R = 137;
|
|
15442
|
+
var V86FS_MSG_SETATTR_R = 138;
|
|
15443
|
+
var V86FS_MSG_FSYNC_R = 139;
|
|
15444
|
+
var V86FS_MSG_UNLINK_R = 140;
|
|
15445
|
+
var V86FS_MSG_RENAME_R = 141;
|
|
15446
|
+
var V86FS_MSG_SYMLINK_R = 142;
|
|
15447
|
+
var V86FS_MSG_READLINK_R = 143;
|
|
15448
|
+
var V86FS_MSG_STATFS_R = 144;
|
|
15449
|
+
var ATTR_MODE = 1;
|
|
15450
|
+
var ATTR_SIZE = 8;
|
|
15451
|
+
var V86FS_STATUS_OK = 0;
|
|
15452
|
+
var V86FS_STATUS_ENOENT = 2;
|
|
15453
|
+
var DT_DIR = 4;
|
|
15454
|
+
var DT_REG = 8;
|
|
15455
|
+
var DT_LNK = 10;
|
|
15456
|
+
var S_IFDIR = 16384;
|
|
15457
|
+
var S_IFREG = 32768;
|
|
15458
|
+
var S_IFLNK = 40960;
|
|
15459
|
+
var textDecoder = new TextDecoder();
|
|
15460
|
+
var textEncoder = new TextEncoder();
|
|
15461
|
+
var FS_ENTRIES = /* @__PURE__ */ new Map([
|
|
15462
|
+
[
|
|
15463
|
+
1,
|
|
15464
|
+
[
|
|
15465
|
+
{
|
|
15466
|
+
inode_id: 2,
|
|
15467
|
+
name: "hello.txt",
|
|
15468
|
+
mode: S_IFREG | 420,
|
|
15469
|
+
size: 12,
|
|
15470
|
+
dt_type: DT_REG,
|
|
15471
|
+
mtime_sec: 17115e5,
|
|
15472
|
+
mtime_nsec: 0,
|
|
15473
|
+
content: textEncoder.encode("hello world\n")
|
|
15474
|
+
},
|
|
15475
|
+
{
|
|
15476
|
+
inode_id: 3,
|
|
15477
|
+
name: "subdir",
|
|
15478
|
+
mode: S_IFDIR | 493,
|
|
15479
|
+
size: 0,
|
|
15480
|
+
dt_type: DT_DIR,
|
|
15481
|
+
mtime_sec: 17115e5,
|
|
15482
|
+
mtime_nsec: 0
|
|
15483
|
+
}
|
|
15484
|
+
]
|
|
15485
|
+
]
|
|
15486
|
+
]);
|
|
15487
|
+
var INODE_MAP = /* @__PURE__ */ new Map([
|
|
15488
|
+
[
|
|
15489
|
+
1,
|
|
15490
|
+
{
|
|
15491
|
+
inode_id: 1,
|
|
15492
|
+
name: "",
|
|
15493
|
+
mode: S_IFDIR | 493,
|
|
15494
|
+
size: 0,
|
|
15495
|
+
dt_type: DT_DIR,
|
|
15496
|
+
mtime_sec: 17115e5,
|
|
15497
|
+
mtime_nsec: 0
|
|
15498
|
+
}
|
|
15499
|
+
]
|
|
15500
|
+
]);
|
|
15501
|
+
for (const entries of FS_ENTRIES.values()) {
|
|
15502
|
+
for (const e of entries) {
|
|
15503
|
+
INODE_MAP.set(e.inode_id, e);
|
|
15504
|
+
}
|
|
15505
|
+
}
|
|
15506
|
+
var V86FS_HDR_SIZE = 7;
|
|
15507
|
+
function packU32(buf, offset, val) {
|
|
15508
|
+
buf[offset] = val & 255;
|
|
15509
|
+
buf[offset + 1] = val >>> 8 & 255;
|
|
15510
|
+
buf[offset + 2] = val >>> 16 & 255;
|
|
15511
|
+
buf[offset + 3] = val >>> 24 & 255;
|
|
15512
|
+
}
|
|
15513
|
+
function packU64(buf, offset, val) {
|
|
15514
|
+
packU32(buf, offset, val);
|
|
15515
|
+
packU32(buf, offset + 4, 0);
|
|
15516
|
+
}
|
|
15517
|
+
function packU16(buf, offset, val) {
|
|
15518
|
+
buf[offset] = val & 255;
|
|
15519
|
+
buf[offset + 1] = val >>> 8 & 255;
|
|
15520
|
+
}
|
|
15521
|
+
function makeResp(size, type, tag) {
|
|
15522
|
+
const resp = new Uint8Array(size);
|
|
15523
|
+
packU32(resp, 0, size);
|
|
15524
|
+
resp[4] = type;
|
|
15525
|
+
resp[5] = tag & 255;
|
|
15526
|
+
resp[6] = tag >> 8 & 255;
|
|
15527
|
+
return resp;
|
|
15528
|
+
}
|
|
15529
|
+
function readU32(buf, offset) {
|
|
15530
|
+
return buf[offset] | buf[offset + 1] << 8 | buf[offset + 2] << 16 | buf[offset + 3] << 24 >>> 0;
|
|
15531
|
+
}
|
|
15532
|
+
function readU16(buf, offset) {
|
|
15533
|
+
return buf[offset] | buf[offset + 1] << 8;
|
|
15534
|
+
}
|
|
15535
|
+
function readU64(buf, offset) {
|
|
15536
|
+
return buf[offset] | buf[offset + 1] << 8 | buf[offset + 2] << 16 | (buf[offset + 3] << 24 >>> 0) + (buf[offset + 4] | buf[offset + 5] << 8 | buf[offset + 6] << 16 | buf[offset + 7] << 24 >>> 0) * 4294967296;
|
|
15537
|
+
}
|
|
15538
|
+
var VirtioV86FS = class {
|
|
15539
|
+
bus;
|
|
15540
|
+
virtio;
|
|
15541
|
+
next_handle_id;
|
|
15542
|
+
next_inode_id;
|
|
15543
|
+
open_handles;
|
|
15544
|
+
// handle_id -> inode_id
|
|
15545
|
+
read_count;
|
|
15546
|
+
constructor(cpu, bus) {
|
|
15547
|
+
this.bus = bus;
|
|
15548
|
+
this.next_handle_id = 1;
|
|
15549
|
+
this.next_inode_id = 100;
|
|
15550
|
+
this.open_handles = /* @__PURE__ */ new Map();
|
|
15551
|
+
this.read_count = 0;
|
|
15552
|
+
const queues = [
|
|
15553
|
+
// Queue 0: hipriq - high-priority metadata (LOOKUP, GETATTR)
|
|
15554
|
+
{ size_supported: 128, notify_offset: 0 },
|
|
15555
|
+
// Queue 1: requestq - data requests (READ, WRITE, READDIR)
|
|
15556
|
+
{ size_supported: 128, notify_offset: 1 },
|
|
15557
|
+
// Queue 2: notifyq - host-to-guest push invalidation
|
|
15558
|
+
{ size_supported: 128, notify_offset: 2 }
|
|
15559
|
+
];
|
|
15560
|
+
this.virtio = new VirtIO(cpu, {
|
|
15561
|
+
name: "virtio-v86fs",
|
|
15562
|
+
pci_id: 14 << 3,
|
|
15563
|
+
device_id: 4223,
|
|
15564
|
+
subsystem_device_id: 63,
|
|
15565
|
+
common: {
|
|
15566
|
+
initial_port: 63488,
|
|
15567
|
+
queues,
|
|
15568
|
+
features: [VIRTIO_F_VERSION_1],
|
|
15569
|
+
on_driver_ok: () => {
|
|
15570
|
+
console.log("v86fs: driver ok");
|
|
15571
|
+
this.bus.send("virtio-v86fs-driver-ok");
|
|
15572
|
+
}
|
|
15573
|
+
},
|
|
15574
|
+
notification: {
|
|
15575
|
+
initial_port: 63744,
|
|
15576
|
+
single_handler: false,
|
|
15577
|
+
handlers: [
|
|
15578
|
+
// Queue 0: hipriq
|
|
15579
|
+
(queue_id) => {
|
|
15580
|
+
this.handle_queue(queue_id);
|
|
15581
|
+
},
|
|
15582
|
+
// Queue 1: requestq
|
|
15583
|
+
(queue_id) => {
|
|
15584
|
+
this.handle_queue(queue_id);
|
|
15585
|
+
},
|
|
15586
|
+
// Queue 2: notifyq
|
|
15587
|
+
(_queue_id) => {
|
|
15588
|
+
dbg_log("v86fs: notifyq notification", LOG_PCI);
|
|
15589
|
+
}
|
|
15590
|
+
]
|
|
15591
|
+
},
|
|
15592
|
+
isr_status: {
|
|
15593
|
+
initial_port: 63232
|
|
15594
|
+
}
|
|
15595
|
+
});
|
|
15596
|
+
}
|
|
15597
|
+
handle_queue(queue_id) {
|
|
15598
|
+
const queue = this.virtio.queues[queue_id];
|
|
15599
|
+
while (queue.has_request()) {
|
|
15600
|
+
const bufchain = queue.pop_request();
|
|
15601
|
+
const req = new Uint8Array(bufchain.length_readable);
|
|
15602
|
+
bufchain.get_next_blob(req);
|
|
15603
|
+
const resp = this.handle_message(req);
|
|
15604
|
+
if (resp && bufchain.length_writable > 0) {
|
|
15605
|
+
bufchain.set_next_blob(resp);
|
|
15606
|
+
}
|
|
15607
|
+
queue.push_reply(bufchain);
|
|
15608
|
+
}
|
|
15609
|
+
queue.flush_replies();
|
|
15610
|
+
}
|
|
15611
|
+
handle_message(req) {
|
|
15612
|
+
if (req.length < V86FS_HDR_SIZE) {
|
|
15613
|
+
console.warn("v86fs: message too short:", req.length);
|
|
15614
|
+
return null;
|
|
15615
|
+
}
|
|
15616
|
+
const type = req[4];
|
|
15617
|
+
const tag = readU16(req, 5);
|
|
15618
|
+
switch (type) {
|
|
15619
|
+
case V86FS_MSG_MOUNT:
|
|
15620
|
+
return this.handle_mount(req, tag);
|
|
15621
|
+
case V86FS_MSG_LOOKUP:
|
|
15622
|
+
return this.handle_lookup(req, tag);
|
|
15623
|
+
case V86FS_MSG_GETATTR:
|
|
15624
|
+
return this.handle_getattr(req, tag);
|
|
15625
|
+
case V86FS_MSG_READDIR:
|
|
15626
|
+
return this.handle_readdir(req, tag);
|
|
15627
|
+
case V86FS_MSG_OPEN:
|
|
15628
|
+
return this.handle_open(req, tag);
|
|
15629
|
+
case V86FS_MSG_CLOSE:
|
|
15630
|
+
return this.handle_close(req, tag);
|
|
15631
|
+
case V86FS_MSG_READ:
|
|
15632
|
+
return this.handle_read(req, tag);
|
|
15633
|
+
case V86FS_MSG_CREATE:
|
|
15634
|
+
return this.handle_create(req, tag);
|
|
15635
|
+
case V86FS_MSG_WRITE:
|
|
15636
|
+
return this.handle_write(req, tag);
|
|
15637
|
+
case V86FS_MSG_MKDIR:
|
|
15638
|
+
return this.handle_mkdir(req, tag);
|
|
15639
|
+
case V86FS_MSG_SETATTR:
|
|
15640
|
+
return this.handle_setattr(req, tag);
|
|
15641
|
+
case V86FS_MSG_FSYNC:
|
|
15642
|
+
return this.handle_fsync(req, tag);
|
|
15643
|
+
case V86FS_MSG_UNLINK:
|
|
15644
|
+
return this.handle_unlink(req, tag);
|
|
15645
|
+
case V86FS_MSG_RENAME:
|
|
15646
|
+
return this.handle_rename(req, tag);
|
|
15647
|
+
case V86FS_MSG_SYMLINK:
|
|
15648
|
+
return this.handle_symlink(req, tag);
|
|
15649
|
+
case V86FS_MSG_READLINK:
|
|
15650
|
+
return this.handle_readlink(req, tag);
|
|
15651
|
+
case V86FS_MSG_STATFS:
|
|
15652
|
+
return this.handle_statfs(tag);
|
|
15653
|
+
default:
|
|
15654
|
+
console.warn("v86fs: unknown message type:", type);
|
|
15655
|
+
return null;
|
|
15656
|
+
}
|
|
15657
|
+
}
|
|
15658
|
+
handle_mount(req, tag) {
|
|
15659
|
+
const name_len = readU16(req, 7);
|
|
15660
|
+
const name = name_len > 0 ? textDecoder.decode(req.subarray(9, 9 + name_len)) : "";
|
|
15661
|
+
console.log("v86fs: mount:", name || "(default)");
|
|
15662
|
+
this.bus.send("virtio-v86fs-mount", name);
|
|
15663
|
+
const resp = new Uint8Array(23);
|
|
15664
|
+
packU32(resp, 0, 23);
|
|
15665
|
+
resp[4] = V86FS_MSG_MOUNT_R;
|
|
15666
|
+
resp[5] = tag & 255;
|
|
15667
|
+
resp[6] = tag >> 8 & 255;
|
|
15668
|
+
packU32(resp, 7, 0);
|
|
15669
|
+
packU64(resp, 11, 1);
|
|
15670
|
+
packU32(resp, 19, 16877);
|
|
15671
|
+
return resp;
|
|
15672
|
+
}
|
|
15673
|
+
handle_getattr(req, tag) {
|
|
15674
|
+
const inode_id = readU64(req, 7);
|
|
15675
|
+
const entry = INODE_MAP.get(inode_id);
|
|
15676
|
+
const resp = makeResp(35, V86FS_MSG_GETATTR_R, tag);
|
|
15677
|
+
if (!entry) {
|
|
15678
|
+
packU32(resp, 7, V86FS_STATUS_ENOENT);
|
|
15679
|
+
return resp;
|
|
15680
|
+
}
|
|
15681
|
+
packU32(resp, 7, V86FS_STATUS_OK);
|
|
15682
|
+
packU32(resp, 11, entry.mode);
|
|
15683
|
+
packU64(resp, 15, entry.size);
|
|
15684
|
+
packU64(resp, 23, entry.mtime_sec);
|
|
15685
|
+
packU32(resp, 31, entry.mtime_nsec);
|
|
15686
|
+
return resp;
|
|
15687
|
+
}
|
|
15688
|
+
handle_lookup(req, tag) {
|
|
15689
|
+
const parent_id = readU64(req, 7);
|
|
15690
|
+
const name_len = readU16(req, 15);
|
|
15691
|
+
const name = textDecoder.decode(req.subarray(17, 17 + name_len));
|
|
15692
|
+
const entries = FS_ENTRIES.get(parent_id);
|
|
15693
|
+
const entry = entries?.find((e) => e.name === name);
|
|
15694
|
+
const resp = new Uint8Array(31);
|
|
15695
|
+
packU32(resp, 0, 31);
|
|
15696
|
+
resp[4] = V86FS_MSG_LOOKUP_R;
|
|
15697
|
+
resp[5] = tag & 255;
|
|
15698
|
+
resp[6] = tag >> 8 & 255;
|
|
15699
|
+
if (!entry) {
|
|
15700
|
+
packU32(resp, 7, V86FS_STATUS_ENOENT);
|
|
15701
|
+
return resp;
|
|
15702
|
+
}
|
|
15703
|
+
packU32(resp, 7, V86FS_STATUS_OK);
|
|
15704
|
+
packU64(resp, 11, entry.inode_id);
|
|
15705
|
+
packU32(resp, 19, entry.mode);
|
|
15706
|
+
packU64(resp, 23, entry.size);
|
|
15707
|
+
return resp;
|
|
15708
|
+
}
|
|
15709
|
+
handle_readdir(req, tag) {
|
|
15710
|
+
const dir_id = readU64(req, 7);
|
|
15711
|
+
const entries = FS_ENTRIES.get(dir_id) || [];
|
|
15712
|
+
const encodedNames = entries.map((e) => textEncoder.encode(e.name));
|
|
15713
|
+
let size = 7 + 4 + 4;
|
|
15714
|
+
for (const nameBytes of encodedNames) {
|
|
15715
|
+
size += 8 + 1 + 2 + nameBytes.length;
|
|
15716
|
+
}
|
|
15717
|
+
const resp = makeResp(size, V86FS_MSG_READDIR_R, tag);
|
|
15718
|
+
packU32(resp, 7, V86FS_STATUS_OK);
|
|
15719
|
+
packU32(resp, 11, entries.length);
|
|
15720
|
+
let off = 15;
|
|
15721
|
+
for (let i = 0; i < entries.length; i++) {
|
|
15722
|
+
const e = entries[i];
|
|
15723
|
+
const nameBytes = encodedNames[i];
|
|
15724
|
+
packU64(resp, off, e.inode_id);
|
|
15725
|
+
resp[off + 8] = e.dt_type;
|
|
15726
|
+
packU16(resp, off + 9, nameBytes.length);
|
|
15727
|
+
resp.set(nameBytes, off + 11);
|
|
15728
|
+
off += 11 + nameBytes.length;
|
|
15729
|
+
}
|
|
15730
|
+
return resp;
|
|
15731
|
+
}
|
|
15732
|
+
handle_open(req, tag) {
|
|
15733
|
+
const inode_id = readU64(req, 7);
|
|
15734
|
+
const handle_id = this.next_handle_id++;
|
|
15735
|
+
this.open_handles.set(handle_id, inode_id);
|
|
15736
|
+
this.bus.send("virtio-v86fs-open", inode_id);
|
|
15737
|
+
const resp = makeResp(19, V86FS_MSG_OPEN_R, tag);
|
|
15738
|
+
packU32(resp, 7, V86FS_STATUS_OK);
|
|
15739
|
+
packU64(resp, 11, handle_id);
|
|
15740
|
+
return resp;
|
|
15741
|
+
}
|
|
15742
|
+
handle_close(req, tag) {
|
|
15743
|
+
const handle_id = readU64(req, 7);
|
|
15744
|
+
this.open_handles.delete(handle_id);
|
|
15745
|
+
this.bus.send("virtio-v86fs-close", handle_id);
|
|
15746
|
+
const resp = makeResp(11, V86FS_MSG_CLOSE_R, tag);
|
|
15747
|
+
packU32(resp, 7, V86FS_STATUS_OK);
|
|
15748
|
+
return resp;
|
|
15749
|
+
}
|
|
15750
|
+
handle_read(req, tag) {
|
|
15751
|
+
const handle_id = readU64(req, 7);
|
|
15752
|
+
const offset = readU64(req, 15);
|
|
15753
|
+
const size = readU32(req, 23);
|
|
15754
|
+
const inode_id = this.open_handles.get(handle_id) ?? handle_id;
|
|
15755
|
+
const entry = INODE_MAP.get(inode_id);
|
|
15756
|
+
const content = entry?.content;
|
|
15757
|
+
this.read_count++;
|
|
15758
|
+
this.bus.send("virtio-v86fs-read", {
|
|
15759
|
+
handle_id,
|
|
15760
|
+
inode_id,
|
|
15761
|
+
offset,
|
|
15762
|
+
size
|
|
15763
|
+
});
|
|
15764
|
+
if (!content || offset >= content.length) {
|
|
15765
|
+
const resp2 = makeResp(15, V86FS_MSG_READ_R, tag);
|
|
15766
|
+
packU32(resp2, 7, V86FS_STATUS_OK);
|
|
15767
|
+
packU32(resp2, 11, 0);
|
|
15768
|
+
return resp2;
|
|
15769
|
+
}
|
|
15770
|
+
const start = Math.min(offset, content.length);
|
|
15771
|
+
const end = Math.min(start + size, content.length);
|
|
15772
|
+
const data = content.subarray(start, end);
|
|
15773
|
+
const resp = new Uint8Array(15 + data.length);
|
|
15774
|
+
packU32(resp, 0, 15 + data.length);
|
|
15775
|
+
resp[4] = V86FS_MSG_READ_R;
|
|
15776
|
+
resp[5] = tag & 255;
|
|
15777
|
+
resp[6] = tag >> 8 & 255;
|
|
15778
|
+
packU32(resp, 7, V86FS_STATUS_OK);
|
|
15779
|
+
packU32(resp, 11, data.length);
|
|
15780
|
+
resp.set(data, 15);
|
|
15781
|
+
return resp;
|
|
15782
|
+
}
|
|
15783
|
+
handle_create(req, tag) {
|
|
15784
|
+
const parent_id = readU64(req, 7);
|
|
15785
|
+
const name_len = readU16(req, 15);
|
|
15786
|
+
const name = textDecoder.decode(req.subarray(17, 17 + name_len));
|
|
15787
|
+
const mode = readU32(req, 17 + name_len);
|
|
15788
|
+
const inode_id = this.next_inode_id++;
|
|
15789
|
+
const entry = {
|
|
15790
|
+
inode_id,
|
|
15791
|
+
name,
|
|
15792
|
+
mode: mode | S_IFREG,
|
|
15793
|
+
size: 0,
|
|
15794
|
+
dt_type: DT_REG,
|
|
15795
|
+
mtime_sec: Math.floor(Date.now() / 1e3),
|
|
15796
|
+
mtime_nsec: 0,
|
|
15797
|
+
content: new Uint8Array(0)
|
|
15798
|
+
};
|
|
15799
|
+
let children = FS_ENTRIES.get(parent_id);
|
|
15800
|
+
if (!children) {
|
|
15801
|
+
children = [];
|
|
15802
|
+
FS_ENTRIES.set(parent_id, children);
|
|
15803
|
+
}
|
|
15804
|
+
children.push(entry);
|
|
15805
|
+
INODE_MAP.set(inode_id, entry);
|
|
15806
|
+
const resp = makeResp(23, V86FS_MSG_CREATE_R, tag);
|
|
15807
|
+
packU32(resp, 7, V86FS_STATUS_OK);
|
|
15808
|
+
packU64(resp, 11, inode_id);
|
|
15809
|
+
packU32(resp, 19, entry.mode);
|
|
15810
|
+
return resp;
|
|
15811
|
+
}
|
|
15812
|
+
handle_write(req, tag) {
|
|
15813
|
+
const inode_id = readU64(req, 7);
|
|
15814
|
+
const offset = readU64(req, 15);
|
|
15815
|
+
const size = readU32(req, 23);
|
|
15816
|
+
const data = req.subarray(27, 27 + size);
|
|
15817
|
+
const entry = INODE_MAP.get(inode_id);
|
|
15818
|
+
if (entry) {
|
|
15819
|
+
const needed = offset + size;
|
|
15820
|
+
if (!entry.content || entry.content.length < needed) {
|
|
15821
|
+
const newContent = new Uint8Array(needed);
|
|
15822
|
+
if (entry.content) {
|
|
15823
|
+
newContent.set(entry.content);
|
|
15824
|
+
}
|
|
15825
|
+
entry.content = newContent;
|
|
15826
|
+
}
|
|
15827
|
+
entry.content.set(data, offset);
|
|
15828
|
+
if (needed > entry.size) {
|
|
15829
|
+
entry.size = needed;
|
|
15830
|
+
}
|
|
15831
|
+
}
|
|
15832
|
+
const resp = makeResp(15, V86FS_MSG_WRITE_R, tag);
|
|
15833
|
+
packU32(resp, 7, V86FS_STATUS_OK);
|
|
15834
|
+
packU32(resp, 11, size);
|
|
15835
|
+
return resp;
|
|
15836
|
+
}
|
|
15837
|
+
handle_mkdir(req, tag) {
|
|
15838
|
+
const parent_id = readU64(req, 7);
|
|
15839
|
+
const name_len = readU16(req, 15);
|
|
15840
|
+
const name = textDecoder.decode(req.subarray(17, 17 + name_len));
|
|
15841
|
+
const mode = readU32(req, 17 + name_len);
|
|
15842
|
+
const inode_id = this.next_inode_id++;
|
|
15843
|
+
const entry = {
|
|
15844
|
+
inode_id,
|
|
15845
|
+
name,
|
|
15846
|
+
mode: mode | S_IFDIR,
|
|
15847
|
+
size: 0,
|
|
15848
|
+
dt_type: DT_DIR,
|
|
15849
|
+
mtime_sec: Math.floor(Date.now() / 1e3),
|
|
15850
|
+
mtime_nsec: 0
|
|
15851
|
+
};
|
|
15852
|
+
let children = FS_ENTRIES.get(parent_id);
|
|
15853
|
+
if (!children) {
|
|
15854
|
+
children = [];
|
|
15855
|
+
FS_ENTRIES.set(parent_id, children);
|
|
15856
|
+
}
|
|
15857
|
+
children.push(entry);
|
|
15858
|
+
INODE_MAP.set(inode_id, entry);
|
|
15859
|
+
FS_ENTRIES.set(inode_id, []);
|
|
15860
|
+
const resp = makeResp(23, V86FS_MSG_MKDIR_R, tag);
|
|
15861
|
+
packU32(resp, 7, V86FS_STATUS_OK);
|
|
15862
|
+
packU64(resp, 11, inode_id);
|
|
15863
|
+
packU32(resp, 19, entry.mode);
|
|
15864
|
+
return resp;
|
|
15865
|
+
}
|
|
15866
|
+
handle_setattr(req, tag) {
|
|
15867
|
+
const inode_id = readU64(req, 7);
|
|
15868
|
+
const valid = readU32(req, 15);
|
|
15869
|
+
const mode = readU32(req, 19);
|
|
15870
|
+
const size = readU64(req, 23);
|
|
15871
|
+
const entry = INODE_MAP.get(inode_id);
|
|
15872
|
+
if (entry) {
|
|
15873
|
+
if (valid & ATTR_MODE) {
|
|
15874
|
+
entry.mode = entry.mode & 61440 | mode & 4095;
|
|
15875
|
+
}
|
|
15876
|
+
if (valid & ATTR_SIZE) {
|
|
15877
|
+
entry.size = size;
|
|
15878
|
+
if (entry.content) {
|
|
15879
|
+
if (size === 0) {
|
|
15880
|
+
entry.content = new Uint8Array(0);
|
|
15881
|
+
} else if (size < entry.content.length) {
|
|
15882
|
+
entry.content = entry.content.subarray(0, size);
|
|
15883
|
+
}
|
|
15884
|
+
}
|
|
15885
|
+
}
|
|
15886
|
+
}
|
|
15887
|
+
const resp = makeResp(11, V86FS_MSG_SETATTR_R, tag);
|
|
15888
|
+
packU32(resp, 7, V86FS_STATUS_OK);
|
|
15889
|
+
return resp;
|
|
15890
|
+
}
|
|
15891
|
+
handle_fsync(req, tag) {
|
|
15892
|
+
const resp = makeResp(11, V86FS_MSG_FSYNC_R, tag);
|
|
15893
|
+
packU32(resp, 7, V86FS_STATUS_OK);
|
|
15894
|
+
return resp;
|
|
15895
|
+
}
|
|
15896
|
+
handle_unlink(req, tag) {
|
|
15897
|
+
const parent_id = readU64(req, 7);
|
|
15898
|
+
const name_len = readU16(req, 15);
|
|
15899
|
+
const name = textDecoder.decode(req.subarray(17, 17 + name_len));
|
|
15900
|
+
const children = FS_ENTRIES.get(parent_id);
|
|
15901
|
+
let status = V86FS_STATUS_ENOENT;
|
|
15902
|
+
if (children) {
|
|
15903
|
+
const idx = children.findIndex((e) => e.name === name);
|
|
15904
|
+
if (idx >= 0) {
|
|
15905
|
+
const entry = children[idx];
|
|
15906
|
+
INODE_MAP.delete(entry.inode_id);
|
|
15907
|
+
FS_ENTRIES.delete(entry.inode_id);
|
|
15908
|
+
children.splice(idx, 1);
|
|
15909
|
+
status = V86FS_STATUS_OK;
|
|
15910
|
+
}
|
|
15911
|
+
}
|
|
15912
|
+
const resp = makeResp(11, V86FS_MSG_UNLINK_R, tag);
|
|
15913
|
+
packU32(resp, 7, status);
|
|
15914
|
+
return resp;
|
|
15915
|
+
}
|
|
15916
|
+
handle_rename(req, tag) {
|
|
15917
|
+
let off = 7;
|
|
15918
|
+
const old_parent_id = readU64(req, off);
|
|
15919
|
+
off += 8;
|
|
15920
|
+
const old_name_len = readU16(req, off);
|
|
15921
|
+
off += 2;
|
|
15922
|
+
const old_name = textDecoder.decode(
|
|
15923
|
+
req.subarray(off, off + old_name_len)
|
|
15924
|
+
);
|
|
15925
|
+
off += old_name_len;
|
|
15926
|
+
const new_parent_id = readU64(req, off);
|
|
15927
|
+
off += 8;
|
|
15928
|
+
const new_name_len = readU16(req, off);
|
|
15929
|
+
off += 2;
|
|
15930
|
+
const new_name = textDecoder.decode(
|
|
15931
|
+
req.subarray(off, off + new_name_len)
|
|
15932
|
+
);
|
|
15933
|
+
let status = V86FS_STATUS_ENOENT;
|
|
15934
|
+
const old_children = FS_ENTRIES.get(old_parent_id);
|
|
15935
|
+
if (old_children) {
|
|
15936
|
+
const idx = old_children.findIndex((e) => e.name === old_name);
|
|
15937
|
+
if (idx >= 0) {
|
|
15938
|
+
const entry = old_children[idx];
|
|
15939
|
+
old_children.splice(idx, 1);
|
|
15940
|
+
entry.name = new_name;
|
|
15941
|
+
let new_children = FS_ENTRIES.get(new_parent_id);
|
|
15942
|
+
if (!new_children) {
|
|
15943
|
+
new_children = [];
|
|
15944
|
+
FS_ENTRIES.set(new_parent_id, new_children);
|
|
15945
|
+
}
|
|
15946
|
+
const existing = new_children.findIndex(
|
|
15947
|
+
(e) => e.name === new_name
|
|
15948
|
+
);
|
|
15949
|
+
if (existing >= 0) {
|
|
15950
|
+
const old_entry = new_children[existing];
|
|
15951
|
+
INODE_MAP.delete(old_entry.inode_id);
|
|
15952
|
+
new_children.splice(existing, 1);
|
|
15953
|
+
}
|
|
15954
|
+
new_children.push(entry);
|
|
15955
|
+
status = V86FS_STATUS_OK;
|
|
15956
|
+
}
|
|
15957
|
+
}
|
|
15958
|
+
const resp = makeResp(11, V86FS_MSG_RENAME_R, tag);
|
|
15959
|
+
packU32(resp, 7, status);
|
|
15960
|
+
return resp;
|
|
15961
|
+
}
|
|
15962
|
+
handle_symlink(req, tag) {
|
|
15963
|
+
let off = 7;
|
|
15964
|
+
const parent_id = readU64(req, off);
|
|
15965
|
+
off += 8;
|
|
15966
|
+
const name_len = readU16(req, off);
|
|
15967
|
+
off += 2;
|
|
15968
|
+
const name = textDecoder.decode(req.subarray(off, off + name_len));
|
|
15969
|
+
off += name_len;
|
|
15970
|
+
const target_len = readU16(req, off);
|
|
15971
|
+
off += 2;
|
|
15972
|
+
const target = textDecoder.decode(req.subarray(off, off + target_len));
|
|
15973
|
+
const inode_id = this.next_inode_id++;
|
|
15974
|
+
const entry = {
|
|
15975
|
+
inode_id,
|
|
15976
|
+
name,
|
|
15977
|
+
mode: S_IFLNK | 511,
|
|
15978
|
+
size: target.length,
|
|
15979
|
+
dt_type: DT_LNK,
|
|
15980
|
+
mtime_sec: Math.floor(Date.now() / 1e3),
|
|
15981
|
+
mtime_nsec: 0,
|
|
15982
|
+
symlink_target: target
|
|
15983
|
+
};
|
|
15984
|
+
let children = FS_ENTRIES.get(parent_id);
|
|
15985
|
+
if (!children) {
|
|
15986
|
+
children = [];
|
|
15987
|
+
FS_ENTRIES.set(parent_id, children);
|
|
15988
|
+
}
|
|
15989
|
+
children.push(entry);
|
|
15990
|
+
INODE_MAP.set(inode_id, entry);
|
|
15991
|
+
const resp = makeResp(23, V86FS_MSG_SYMLINK_R, tag);
|
|
15992
|
+
packU32(resp, 7, V86FS_STATUS_OK);
|
|
15993
|
+
packU64(resp, 11, inode_id);
|
|
15994
|
+
packU32(resp, 19, entry.mode);
|
|
15995
|
+
return resp;
|
|
15996
|
+
}
|
|
15997
|
+
handle_readlink(req, tag) {
|
|
15998
|
+
const inode_id = readU64(req, 7);
|
|
15999
|
+
const entry = INODE_MAP.get(inode_id);
|
|
16000
|
+
if (!entry || !entry.symlink_target) {
|
|
16001
|
+
const resp2 = makeResp(11, V86FS_MSG_READLINK_R, tag);
|
|
16002
|
+
packU32(resp2, 7, V86FS_STATUS_ENOENT);
|
|
16003
|
+
return resp2;
|
|
16004
|
+
}
|
|
16005
|
+
const target_bytes = textEncoder.encode(entry.symlink_target);
|
|
16006
|
+
const resp_len = 11 + 2 + target_bytes.length;
|
|
16007
|
+
const resp = makeResp(resp_len, V86FS_MSG_READLINK_R, tag);
|
|
16008
|
+
packU32(resp, 7, V86FS_STATUS_OK);
|
|
16009
|
+
packU16(resp, 11, target_bytes.length);
|
|
16010
|
+
resp.set(target_bytes, 13);
|
|
16011
|
+
return resp;
|
|
16012
|
+
}
|
|
16013
|
+
handle_statfs(tag) {
|
|
16014
|
+
const resp = makeResp(55, V86FS_MSG_STATFS_R, tag);
|
|
16015
|
+
packU32(resp, 7, V86FS_STATUS_OK);
|
|
16016
|
+
packU64(resp, 11, 1024 * 1024);
|
|
16017
|
+
packU64(resp, 19, 512 * 1024);
|
|
16018
|
+
packU64(resp, 27, 512 * 1024);
|
|
16019
|
+
packU64(resp, 35, 1024 * 1024);
|
|
16020
|
+
packU64(resp, 43, 512 * 1024);
|
|
16021
|
+
packU32(resp, 51, 4096);
|
|
16022
|
+
return resp;
|
|
16023
|
+
}
|
|
16024
|
+
/** Push an INVALIDATE notification to the guest via notifyq.
|
|
16025
|
+
* Guest kernel will invalidate page cache for the given inode. */
|
|
16026
|
+
invalidate_inode(inode_id) {
|
|
16027
|
+
const queue = this.virtio.queues[2];
|
|
16028
|
+
if (!queue.has_request()) return false;
|
|
16029
|
+
const bufchain = queue.pop_request();
|
|
16030
|
+
const msg = new Uint8Array(15);
|
|
16031
|
+
packU32(msg, 0, 15);
|
|
16032
|
+
msg[4] = V86FS_MSG_INVALIDATE;
|
|
16033
|
+
packU16(msg, 5, 0);
|
|
16034
|
+
packU64(msg, 7, inode_id);
|
|
16035
|
+
bufchain.set_next_blob(msg);
|
|
16036
|
+
queue.push_reply(bufchain);
|
|
16037
|
+
queue.flush_replies();
|
|
16038
|
+
return true;
|
|
16039
|
+
}
|
|
16040
|
+
/** Push an INVALIDATE_DIR notification to the guest via notifyq.
|
|
16041
|
+
* Guest kernel will invalidate dcache for the given directory inode. */
|
|
16042
|
+
invalidate_dir(inode_id) {
|
|
16043
|
+
const queue = this.virtio.queues[2];
|
|
16044
|
+
if (!queue.has_request()) return false;
|
|
16045
|
+
const bufchain = queue.pop_request();
|
|
16046
|
+
const msg = new Uint8Array(15);
|
|
16047
|
+
packU32(msg, 0, 15);
|
|
16048
|
+
msg[4] = V86FS_MSG_INVALIDATE_DIR;
|
|
16049
|
+
packU16(msg, 5, 0);
|
|
16050
|
+
packU64(msg, 7, inode_id);
|
|
16051
|
+
bufchain.set_next_blob(msg);
|
|
16052
|
+
queue.push_reply(bufchain);
|
|
16053
|
+
queue.flush_replies();
|
|
16054
|
+
return true;
|
|
16055
|
+
}
|
|
16056
|
+
get_state() {
|
|
16057
|
+
const state = [];
|
|
16058
|
+
state[0] = this.virtio;
|
|
16059
|
+
return state;
|
|
16060
|
+
}
|
|
16061
|
+
set_state(state) {
|
|
16062
|
+
this.virtio.set_state(state[0]);
|
|
16063
|
+
}
|
|
16064
|
+
};
|
|
16065
|
+
|
|
15141
16066
|
// lib/filesystem.ts
|
|
15142
16067
|
var S_IFMT = 61440;
|
|
15143
16068
|
var S_IFSOCK = 49152;
|
|
15144
|
-
var
|
|
15145
|
-
var
|
|
15146
|
-
var
|
|
16069
|
+
var S_IFLNK2 = 40960;
|
|
16070
|
+
var S_IFREG2 = 32768;
|
|
16071
|
+
var S_IFDIR2 = 16384;
|
|
15147
16072
|
var STATUS_INVALID = -1;
|
|
15148
16073
|
var STATUS_OK = 0;
|
|
15149
16074
|
var STATUS_ON_STORAGE = 2;
|
|
@@ -15236,11 +16161,11 @@ var V86Starter = (() => {
|
|
|
15236
16161
|
get_state() {
|
|
15237
16162
|
const state = [];
|
|
15238
16163
|
state[0] = this.mode;
|
|
15239
|
-
if ((this.mode & S_IFMT) ===
|
|
16164
|
+
if ((this.mode & S_IFMT) === S_IFDIR2) {
|
|
15240
16165
|
state[1] = [...this.direntries];
|
|
15241
|
-
} else if ((this.mode & S_IFMT) ===
|
|
16166
|
+
} else if ((this.mode & S_IFMT) === S_IFREG2) {
|
|
15242
16167
|
state[1] = this.sha256sum;
|
|
15243
|
-
} else if ((this.mode & S_IFMT) ===
|
|
16168
|
+
} else if ((this.mode & S_IFMT) === S_IFLNK2) {
|
|
15244
16169
|
state[1] = this.symlink;
|
|
15245
16170
|
} else if ((this.mode & S_IFMT) === S_IFSOCK) {
|
|
15246
16171
|
state[1] = [this.minor, this.major];
|
|
@@ -15263,14 +16188,14 @@ var V86Starter = (() => {
|
|
|
15263
16188
|
}
|
|
15264
16189
|
set_state(state) {
|
|
15265
16190
|
this.mode = state[0];
|
|
15266
|
-
if ((this.mode & S_IFMT) ===
|
|
16191
|
+
if ((this.mode & S_IFMT) === S_IFDIR2) {
|
|
15267
16192
|
this.direntries = /* @__PURE__ */ new Map();
|
|
15268
16193
|
for (const [name, entry] of state[1]) {
|
|
15269
16194
|
this.direntries.set(name, entry);
|
|
15270
16195
|
}
|
|
15271
|
-
} else if ((this.mode & S_IFMT) ===
|
|
16196
|
+
} else if ((this.mode & S_IFMT) === S_IFREG2) {
|
|
15272
16197
|
this.sha256sum = state[1];
|
|
15273
|
-
} else if ((this.mode & S_IFMT) ===
|
|
16198
|
+
} else if ((this.mode & S_IFMT) === S_IFLNK2) {
|
|
15274
16199
|
this.symlink = state[1];
|
|
15275
16200
|
} else if ((this.mode & S_IFMT) === S_IFSOCK) {
|
|
15276
16201
|
;
|
|
@@ -15339,7 +16264,7 @@ var V86Starter = (() => {
|
|
|
15339
16264
|
state[1] = this.qidcounter.last_qidnumber;
|
|
15340
16265
|
state[2] = [];
|
|
15341
16266
|
for (const [id, data] of Object.entries(this.inodedata)) {
|
|
15342
|
-
if ((this.inodes[Number(id)].mode &
|
|
16267
|
+
if ((this.inodes[Number(id)].mode & S_IFDIR2) === 0) {
|
|
15343
16268
|
state[2].push([id, data]);
|
|
15344
16269
|
}
|
|
15345
16270
|
}
|
|
@@ -15390,15 +16315,15 @@ var V86Starter = (() => {
|
|
|
15390
16315
|
inode.uid = data[JSONFS_IDX_UID];
|
|
15391
16316
|
inode.gid = data[JSONFS_IDX_GID];
|
|
15392
16317
|
const ifmt = inode.mode & S_IFMT;
|
|
15393
|
-
if (ifmt ===
|
|
16318
|
+
if (ifmt === S_IFDIR2) {
|
|
15394
16319
|
this.PushInode(inode, parentid, name);
|
|
15395
16320
|
this.LoadDir(this.inodes.length - 1, data[JSONFS_IDX_TARGET]);
|
|
15396
|
-
} else if (ifmt ===
|
|
16321
|
+
} else if (ifmt === S_IFREG2) {
|
|
15397
16322
|
inode.status = STATUS_ON_STORAGE;
|
|
15398
16323
|
inode.sha256sum = data[JSONFS_IDX_SHA256];
|
|
15399
16324
|
dbg_assert(!!inode.sha256sum);
|
|
15400
16325
|
this.PushInode(inode, parentid, name);
|
|
15401
|
-
} else if (ifmt ===
|
|
16326
|
+
} else if (ifmt === S_IFLNK2) {
|
|
15402
16327
|
inode.symlink = data[JSONFS_IDX_TARGET];
|
|
15403
16328
|
this.PushInode(inode, parentid, name);
|
|
15404
16329
|
} else if (ifmt === S_IFSOCK) {
|
|
@@ -15570,13 +16495,13 @@ var V86Starter = (() => {
|
|
|
15570
16495
|
return this.create_forwarder(parent_inode.mount_id, foreign_id);
|
|
15571
16496
|
}
|
|
15572
16497
|
const x = this.CreateInode();
|
|
15573
|
-
x.mode = 511 |
|
|
16498
|
+
x.mode = 511 | S_IFDIR2;
|
|
15574
16499
|
if (parentid >= 0) {
|
|
15575
16500
|
x.uid = this.inodes[parentid].uid;
|
|
15576
16501
|
x.gid = this.inodes[parentid].gid;
|
|
15577
|
-
x.mode = this.inodes[parentid].mode & 511 |
|
|
16502
|
+
x.mode = this.inodes[parentid].mode & 511 | S_IFDIR2;
|
|
15578
16503
|
}
|
|
15579
|
-
x.qid.type =
|
|
16504
|
+
x.qid.type = S_IFDIR2 >> 8;
|
|
15580
16505
|
this.PushInode(x, parentid, name);
|
|
15581
16506
|
this.NotifyListeners(this.inodes.length - 1, "newdir");
|
|
15582
16507
|
return this.inodes.length - 1;
|
|
@@ -15594,8 +16519,8 @@ var V86Starter = (() => {
|
|
|
15594
16519
|
const x = this.CreateInode();
|
|
15595
16520
|
x.uid = this.inodes[parentid].uid;
|
|
15596
16521
|
x.gid = this.inodes[parentid].gid;
|
|
15597
|
-
x.qid.type =
|
|
15598
|
-
x.mode = this.inodes[parentid].mode & 438 |
|
|
16522
|
+
x.qid.type = S_IFREG2 >> 8;
|
|
16523
|
+
x.mode = this.inodes[parentid].mode & 438 | S_IFREG2;
|
|
15599
16524
|
this.PushInode(x, parentid, filename);
|
|
15600
16525
|
this.NotifyListeners(this.inodes.length - 1, "newfile");
|
|
15601
16526
|
return this.inodes.length - 1;
|
|
@@ -15636,9 +16561,9 @@ var V86Starter = (() => {
|
|
|
15636
16561
|
const x = this.CreateInode();
|
|
15637
16562
|
x.uid = this.inodes[parentid].uid;
|
|
15638
16563
|
x.gid = this.inodes[parentid].gid;
|
|
15639
|
-
x.qid.type =
|
|
16564
|
+
x.qid.type = S_IFLNK2 >> 8;
|
|
15640
16565
|
x.symlink = symlink;
|
|
15641
|
-
x.mode =
|
|
16566
|
+
x.mode = S_IFLNK2;
|
|
15642
16567
|
this.PushInode(x, parentid, filename);
|
|
15643
16568
|
return this.inodes.length - 1;
|
|
15644
16569
|
}
|
|
@@ -15683,7 +16608,7 @@ var V86Starter = (() => {
|
|
|
15683
16608
|
if (this.is_forwarder(inode)) {
|
|
15684
16609
|
return await this.follow_fs(inode).OpenInode(inode.foreign_id, mode);
|
|
15685
16610
|
}
|
|
15686
|
-
if ((inode.mode & S_IFMT) ===
|
|
16611
|
+
if ((inode.mode & S_IFMT) === S_IFDIR2) {
|
|
15687
16612
|
this.FillDirectory(id);
|
|
15688
16613
|
}
|
|
15689
16614
|
}
|
|
@@ -16038,7 +16963,7 @@ var V86Starter = (() => {
|
|
|
16038
16963
|
let parentid = -1;
|
|
16039
16964
|
let id = 0;
|
|
16040
16965
|
let forward_path = null;
|
|
16041
|
-
let i
|
|
16966
|
+
let i;
|
|
16042
16967
|
for (i = 0; i < n; i++) {
|
|
16043
16968
|
parentid = id;
|
|
16044
16969
|
id = this.Search(parentid, walk[i]);
|
|
@@ -16104,13 +17029,13 @@ var V86Starter = (() => {
|
|
|
16104
17029
|
DeleteNode(path) {
|
|
16105
17030
|
const ids = this.SearchPath(path);
|
|
16106
17031
|
if (ids.id === -1) return;
|
|
16107
|
-
if ((this.inodes[ids.id].mode & S_IFMT) ===
|
|
17032
|
+
if ((this.inodes[ids.id].mode & S_IFMT) === S_IFREG2) {
|
|
16108
17033
|
const ret = this.Unlink(ids.parentid, ids.name);
|
|
16109
17034
|
dbg_assert(
|
|
16110
17035
|
ret === 0,
|
|
16111
17036
|
"Filesystem DeleteNode failed with error code: " + -ret
|
|
16112
17037
|
);
|
|
16113
|
-
} else if ((this.inodes[ids.id].mode & S_IFMT) ===
|
|
17038
|
+
} else if ((this.inodes[ids.id].mode & S_IFMT) === S_IFDIR2) {
|
|
16114
17039
|
this.RecursiveDelete(path);
|
|
16115
17040
|
const ret = this.Unlink(ids.parentid, ids.name);
|
|
16116
17041
|
dbg_assert(
|
|
@@ -16214,7 +17139,7 @@ var V86Starter = (() => {
|
|
|
16214
17139
|
if (this.is_forwarder(inode)) {
|
|
16215
17140
|
return this.follow_fs(inode).IsDirectory(inode.foreign_id);
|
|
16216
17141
|
}
|
|
16217
|
-
return (inode.mode & S_IFMT) ===
|
|
17142
|
+
return (inode.mode & S_IFMT) === S_IFDIR2;
|
|
16218
17143
|
}
|
|
16219
17144
|
IsEmpty(idx) {
|
|
16220
17145
|
const inode = this.inodes[idx];
|
|
@@ -16744,7 +17669,7 @@ var V86Starter = (() => {
|
|
|
16744
17669
|
bufchain.get_next_blob(buffer);
|
|
16745
17670
|
const state = { offset: 0 };
|
|
16746
17671
|
const header = Unmarshall(["w", "b", "h"], buffer, state);
|
|
16747
|
-
let size
|
|
17672
|
+
let size;
|
|
16748
17673
|
const id = header[1];
|
|
16749
17674
|
const tag = header[2];
|
|
16750
17675
|
switch (id) {
|
|
@@ -16805,7 +17730,7 @@ var V86Starter = (() => {
|
|
|
16805
17730
|
name
|
|
16806
17731
|
);
|
|
16807
17732
|
if (ret < 0) {
|
|
16808
|
-
let error_message
|
|
17733
|
+
let error_message;
|
|
16809
17734
|
if (ret === -EPERM)
|
|
16810
17735
|
error_message = "Operation not permitted";
|
|
16811
17736
|
else {
|
|
@@ -16918,7 +17843,7 @@ var V86Starter = (() => {
|
|
|
16918
17843
|
this.fids[fid].inodeid
|
|
16919
17844
|
);
|
|
16920
17845
|
const inode = this.fs.GetInode(idx);
|
|
16921
|
-
inode.mode = mode |
|
|
17846
|
+
inode.mode = mode | S_IFDIR2;
|
|
16922
17847
|
inode.uid = this.fids[fid].uid;
|
|
16923
17848
|
inode.gid = gid;
|
|
16924
17849
|
Marshall(["Q"], [inode.qid], this.replybuffer, 7);
|
|
@@ -16949,7 +17874,7 @@ var V86Starter = (() => {
|
|
|
16949
17874
|
const inode = this.fs.GetInode(idx);
|
|
16950
17875
|
inode.uid = this.fids[fid].uid;
|
|
16951
17876
|
inode.gid = gid;
|
|
16952
|
-
inode.mode = mode |
|
|
17877
|
+
inode.mode = mode | S_IFREG2;
|
|
16953
17878
|
Marshall(
|
|
16954
17879
|
["Q", "w"],
|
|
16955
17880
|
[inode.qid, this.msize - 24],
|
|
@@ -17274,7 +18199,7 @@ var V86Starter = (() => {
|
|
|
17274
18199
|
newname
|
|
17275
18200
|
);
|
|
17276
18201
|
if (ret < 0) {
|
|
17277
|
-
let error_message
|
|
18202
|
+
let error_message;
|
|
17278
18203
|
if (ret === -ENOENT)
|
|
17279
18204
|
error_message = "No such file or directory";
|
|
17280
18205
|
else if (ret === -EPERM)
|
|
@@ -17323,7 +18248,7 @@ var V86Starter = (() => {
|
|
|
17323
18248
|
}
|
|
17324
18249
|
const ret = this.fs.Unlink(this.fids[dirfd].inodeid, name);
|
|
17325
18250
|
if (ret < 0) {
|
|
17326
|
-
let error_message
|
|
18251
|
+
let error_message;
|
|
17327
18252
|
if (ret === -ENOTEMPTY)
|
|
17328
18253
|
error_message = "Directory not empty";
|
|
17329
18254
|
else if (ret === -EPERM)
|
|
@@ -17975,7 +18900,6 @@ var V86Starter = (() => {
|
|
|
17975
18900
|
get_eflags;
|
|
17976
18901
|
handle_irqs;
|
|
17977
18902
|
main_loop;
|
|
17978
|
-
reboot_internal;
|
|
17979
18903
|
set_jit_config;
|
|
17980
18904
|
read8;
|
|
17981
18905
|
read16;
|
|
@@ -18024,10 +18948,10 @@ var V86Starter = (() => {
|
|
|
18024
18948
|
this.name = "cpu";
|
|
18025
18949
|
this.stop_idling = stop_idling;
|
|
18026
18950
|
this.wm = wm;
|
|
18951
|
+
this.wasm_memory = wm.wasm_memory;
|
|
18027
18952
|
this.wasm_patch();
|
|
18028
18953
|
this.create_jit_imports();
|
|
18029
|
-
const memory = this.
|
|
18030
|
-
this.wasm_memory = memory;
|
|
18954
|
+
const memory = this.wasm_memory;
|
|
18031
18955
|
this.memory_size = view(Uint32Array, memory, 812, 1);
|
|
18032
18956
|
this.mem8 = new Uint8Array(0);
|
|
18033
18957
|
this.mem32s = new Int32Array(this.mem8.buffer);
|
|
@@ -18172,7 +19096,7 @@ var V86Starter = (() => {
|
|
|
18172
19096
|
}
|
|
18173
19097
|
create_jit_imports() {
|
|
18174
19098
|
const jit_imports = /* @__PURE__ */ Object.create(null);
|
|
18175
|
-
jit_imports["m"] = this.
|
|
19099
|
+
jit_imports["m"] = this.wasm_memory;
|
|
18176
19100
|
for (const name of Object.keys(this.wm.exports)) {
|
|
18177
19101
|
if (name.startsWith("_") || name.startsWith("zstd") || name.endsWith("_js")) {
|
|
18178
19102
|
continue;
|
|
@@ -18193,7 +19117,6 @@ var V86Starter = (() => {
|
|
|
18193
19117
|
this.get_eflags = get_import("get_eflags");
|
|
18194
19118
|
this.handle_irqs = get_import("handle_irqs");
|
|
18195
19119
|
this.main_loop = get_import("main_loop");
|
|
18196
|
-
this.reboot_internal = get_import("reboot_internal");
|
|
18197
19120
|
this.set_jit_config = get_import("set_jit_config");
|
|
18198
19121
|
this.read8 = get_import("read8");
|
|
18199
19122
|
this.read16 = get_import("read16");
|
|
@@ -18350,6 +19273,8 @@ var V86Starter = (() => {
|
|
|
18350
19273
|
state[86] = this.last_result;
|
|
18351
19274
|
state[87] = this.fpu_status_word;
|
|
18352
19275
|
state[88] = this.mxcsr;
|
|
19276
|
+
state[89] = this.devices.virtio_mem;
|
|
19277
|
+
state[90] = this.devices.virtio_v86fs;
|
|
18353
19278
|
return state;
|
|
18354
19279
|
}
|
|
18355
19280
|
get_state_pic() {
|
|
@@ -18410,6 +19335,25 @@ var V86Starter = (() => {
|
|
|
18410
19335
|
IOAPIC_STRUCT_SIZE
|
|
18411
19336
|
);
|
|
18412
19337
|
}
|
|
19338
|
+
resize_memory(new_size) {
|
|
19339
|
+
const mem8_offset = this.mem8.byteOffset;
|
|
19340
|
+
const needed_total = mem8_offset + new_size;
|
|
19341
|
+
const current_buffer = this.wasm_memory.buffer.byteLength;
|
|
19342
|
+
if (needed_total > current_buffer) {
|
|
19343
|
+
const grow_pages = Math.ceil(
|
|
19344
|
+
(needed_total - current_buffer) / WASM_PAGE_SIZE
|
|
19345
|
+
);
|
|
19346
|
+
this.wasm_memory.grow(grow_pages);
|
|
19347
|
+
}
|
|
19348
|
+
this.mem8 = view(Uint8Array, this.wasm_memory, mem8_offset, new_size);
|
|
19349
|
+
this.mem32s = view(
|
|
19350
|
+
Int32Array,
|
|
19351
|
+
this.wasm_memory,
|
|
19352
|
+
mem8_offset,
|
|
19353
|
+
new_size >> 2
|
|
19354
|
+
);
|
|
19355
|
+
this.memory_size[0] = new_size;
|
|
19356
|
+
}
|
|
18413
19357
|
set_state(state) {
|
|
18414
19358
|
this.memory_size[0] = state[0];
|
|
18415
19359
|
if (this.mem8.length !== this.memory_size[0]) {
|
|
@@ -18509,6 +19453,10 @@ var V86Starter = (() => {
|
|
|
18509
19453
|
this.devices.virtio_net.set_state(state[83]);
|
|
18510
19454
|
if (this.devices.virtio_balloon)
|
|
18511
19455
|
this.devices.virtio_balloon.set_state(state[84]);
|
|
19456
|
+
if (this.devices.virtio_mem && state[89])
|
|
19457
|
+
this.devices.virtio_mem.set_state(state[89]);
|
|
19458
|
+
if (this.devices.virtio_v86fs && state[90])
|
|
19459
|
+
this.devices.virtio_v86fs.set_state(state[90]);
|
|
18512
19460
|
this.fw_value = state[62];
|
|
18513
19461
|
if (state[63]) this.set_state_ioapic(state[63]);
|
|
18514
19462
|
this.tss_size_32[0] = state[64];
|
|
@@ -18919,6 +19867,19 @@ var V86Starter = (() => {
|
|
|
18919
19867
|
device_bus
|
|
18920
19868
|
);
|
|
18921
19869
|
}
|
|
19870
|
+
if (settings.virtio_mem) {
|
|
19871
|
+
const mem_cfg = settings.virtio_mem;
|
|
19872
|
+
this.devices.virtio_mem = new VirtioMem(
|
|
19873
|
+
this,
|
|
19874
|
+
device_bus,
|
|
19875
|
+
mem_cfg.region_addr,
|
|
19876
|
+
mem_cfg.region_size,
|
|
19877
|
+
mem_cfg.block_size
|
|
19878
|
+
);
|
|
19879
|
+
}
|
|
19880
|
+
if (settings.virtio_v86fs) {
|
|
19881
|
+
this.devices.virtio_v86fs = new VirtioV86FS(this, device_bus);
|
|
19882
|
+
}
|
|
18922
19883
|
this.devices.sb16 = new SB16(this, device_bus);
|
|
18923
19884
|
}
|
|
18924
19885
|
if (settings.multiboot) {
|
|
@@ -19144,7 +20105,6 @@ var V86Starter = (() => {
|
|
|
19144
20105
|
cpu.write32(multiboot_data + 4, ramdisk_top);
|
|
19145
20106
|
cpu.write32(multiboot_data + 8, 0);
|
|
19146
20107
|
cpu.write32(multiboot_data + 12, 0);
|
|
19147
|
-
multiboot_data += 16;
|
|
19148
20108
|
dbg_assert(ramdisk_top < cpu.memory_size[0]);
|
|
19149
20109
|
cpu.write_blob(new Uint8Array(initrd), ramdisk_address);
|
|
19150
20110
|
}
|
|
@@ -25218,20 +26178,12 @@ ${e.stack || e.message}`
|
|
|
25218
26178
|
};
|
|
25219
26179
|
|
|
25220
26180
|
// src/browser/starter.ts
|
|
25221
|
-
var
|
|
25222
|
-
|
|
25223
|
-
constructor(message) {
|
|
25224
|
-
this.message = message || "File already exists";
|
|
25225
|
-
}
|
|
25226
|
-
};
|
|
25227
|
-
FileExistsError.prototype = Error.prototype;
|
|
25228
|
-
var FileNotFoundError = class {
|
|
25229
|
-
message;
|
|
26181
|
+
var import_meta = {};
|
|
26182
|
+
var FileNotFoundError = class extends Error {
|
|
25230
26183
|
constructor(message) {
|
|
25231
|
-
|
|
26184
|
+
super(message || "File not found");
|
|
25232
26185
|
}
|
|
25233
26186
|
};
|
|
25234
|
-
FileNotFoundError.prototype = Error.prototype;
|
|
25235
26187
|
var V86 = class {
|
|
25236
26188
|
cpu_is_running = false;
|
|
25237
26189
|
cpu_exception_hook = function(_n) {
|
|
@@ -25357,9 +26309,10 @@ ${e.stack || e.message}`
|
|
|
25357
26309
|
"v86.wasm",
|
|
25358
26310
|
"v86-fallback.wasm"
|
|
25359
26311
|
);
|
|
25360
|
-
} else if (typeof window === "undefined"
|
|
25361
|
-
|
|
25362
|
-
|
|
26312
|
+
} else if (typeof window === "undefined") {
|
|
26313
|
+
const root = new URL("../../", import_meta.url).pathname;
|
|
26314
|
+
v86_bin = root + "build/" + v86_bin;
|
|
26315
|
+
v86_bin_fallback = root + "build/" + v86_bin_fallback;
|
|
25363
26316
|
} else {
|
|
25364
26317
|
v86_bin = "build/" + v86_bin;
|
|
25365
26318
|
v86_bin_fallback = "build/" + v86_bin_fallback;
|
|
@@ -25402,7 +26355,8 @@ ${e.stack || e.message}`
|
|
|
25402
26355
|
exports["rust_init"]();
|
|
25403
26356
|
const emulator = this.v86 = new v86(this.emulator_bus, {
|
|
25404
26357
|
exports,
|
|
25405
|
-
wasm_table
|
|
26358
|
+
wasm_table,
|
|
26359
|
+
wasm_memory
|
|
25406
26360
|
});
|
|
25407
26361
|
cpu = emulator.cpu;
|
|
25408
26362
|
this.continue_init(emulator, options);
|
|
@@ -25444,7 +26398,9 @@ ${e.stack || e.message}`
|
|
|
25444
26398
|
settings.mac_address_translation = options.mac_address_translation;
|
|
25445
26399
|
settings.cpuid_level = options.cpuid_level;
|
|
25446
26400
|
settings.virtio_balloon = options.virtio_balloon;
|
|
26401
|
+
settings.virtio_mem = options.virtio_mem;
|
|
25447
26402
|
settings.virtio_console = !!options.virtio_console;
|
|
26403
|
+
settings.virtio_v86fs = !!options.virtio_v86fs;
|
|
25448
26404
|
const relay_url = options.network_relay_url || options.net_device && options.net_device.relay_url;
|
|
25449
26405
|
if (relay_url) {
|
|
25450
26406
|
if (relay_url === "fetch") {
|