@aptre/v86 0.5.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.
Files changed (111) hide show
  1. package/LICENSE +22 -0
  2. package/LICENSE.MIT +22 -0
  3. package/Readme.md +237 -0
  4. package/dist/v86.browser.js +26666 -0
  5. package/dist/v86.browser.js.map +7 -0
  6. package/dist/v86.js +26632 -0
  7. package/dist/v86.js.map +7 -0
  8. package/gen/generate_analyzer.ts +512 -0
  9. package/gen/generate_interpreter.ts +522 -0
  10. package/gen/generate_jit.ts +624 -0
  11. package/gen/rust_ast.ts +107 -0
  12. package/gen/util.ts +35 -0
  13. package/gen/x86_table.ts +1836 -0
  14. package/lib/9p.ts +1547 -0
  15. package/lib/filesystem.ts +1879 -0
  16. package/lib/marshall.ts +168 -0
  17. package/lib/softfloat/softfloat.c +32501 -0
  18. package/lib/zstd/zstddeclib.c +13520 -0
  19. package/package.json +75 -0
  20. package/src/acpi.ts +267 -0
  21. package/src/browser/dummy_screen.ts +106 -0
  22. package/src/browser/fake_network.ts +1771 -0
  23. package/src/browser/fetch_network.ts +361 -0
  24. package/src/browser/filestorage.ts +124 -0
  25. package/src/browser/inbrowser_network.ts +57 -0
  26. package/src/browser/keyboard.ts +564 -0
  27. package/src/browser/main.ts +3415 -0
  28. package/src/browser/mouse.ts +255 -0
  29. package/src/browser/network.ts +142 -0
  30. package/src/browser/print_stats.ts +336 -0
  31. package/src/browser/screen.ts +978 -0
  32. package/src/browser/serial.ts +316 -0
  33. package/src/browser/speaker.ts +1223 -0
  34. package/src/browser/starter.ts +1688 -0
  35. package/src/browser/wisp_network.ts +332 -0
  36. package/src/browser/worker_bus.ts +64 -0
  37. package/src/buffer.ts +652 -0
  38. package/src/bus.ts +78 -0
  39. package/src/const.ts +128 -0
  40. package/src/cpu.ts +2891 -0
  41. package/src/dma.ts +474 -0
  42. package/src/elf.ts +251 -0
  43. package/src/floppy.ts +1778 -0
  44. package/src/ide.ts +3455 -0
  45. package/src/io.ts +504 -0
  46. package/src/iso9660.ts +317 -0
  47. package/src/kernel.ts +250 -0
  48. package/src/lib.ts +645 -0
  49. package/src/log.ts +149 -0
  50. package/src/main.ts +199 -0
  51. package/src/ne2k.ts +1589 -0
  52. package/src/pci.ts +815 -0
  53. package/src/pit.ts +406 -0
  54. package/src/ps2.ts +820 -0
  55. package/src/rtc.ts +537 -0
  56. package/src/rust/analysis.rs +101 -0
  57. package/src/rust/codegen.rs +2660 -0
  58. package/src/rust/config.rs +3 -0
  59. package/src/rust/control_flow.rs +425 -0
  60. package/src/rust/cpu/apic.rs +658 -0
  61. package/src/rust/cpu/arith.rs +1207 -0
  62. package/src/rust/cpu/call_indirect.rs +2 -0
  63. package/src/rust/cpu/cpu.rs +4501 -0
  64. package/src/rust/cpu/fpu.rs +923 -0
  65. package/src/rust/cpu/global_pointers.rs +112 -0
  66. package/src/rust/cpu/instructions.rs +2486 -0
  67. package/src/rust/cpu/instructions_0f.rs +5261 -0
  68. package/src/rust/cpu/ioapic.rs +316 -0
  69. package/src/rust/cpu/memory.rs +351 -0
  70. package/src/rust/cpu/misc_instr.rs +613 -0
  71. package/src/rust/cpu/mod.rs +16 -0
  72. package/src/rust/cpu/modrm.rs +133 -0
  73. package/src/rust/cpu/pic.rs +402 -0
  74. package/src/rust/cpu/sse_instr.rs +361 -0
  75. package/src/rust/cpu/string.rs +701 -0
  76. package/src/rust/cpu/vga.rs +175 -0
  77. package/src/rust/cpu_context.rs +69 -0
  78. package/src/rust/dbg.rs +98 -0
  79. package/src/rust/gen/analyzer.rs +3807 -0
  80. package/src/rust/gen/analyzer0f.rs +3992 -0
  81. package/src/rust/gen/interpreter.rs +4447 -0
  82. package/src/rust/gen/interpreter0f.rs +5404 -0
  83. package/src/rust/gen/jit.rs +5080 -0
  84. package/src/rust/gen/jit0f.rs +5547 -0
  85. package/src/rust/gen/mod.rs +14 -0
  86. package/src/rust/jit.rs +2443 -0
  87. package/src/rust/jit_instructions.rs +7881 -0
  88. package/src/rust/js_api.rs +6 -0
  89. package/src/rust/leb.rs +46 -0
  90. package/src/rust/lib.rs +29 -0
  91. package/src/rust/modrm.rs +330 -0
  92. package/src/rust/opstats.rs +249 -0
  93. package/src/rust/page.rs +15 -0
  94. package/src/rust/paging.rs +25 -0
  95. package/src/rust/prefix.rs +15 -0
  96. package/src/rust/profiler.rs +155 -0
  97. package/src/rust/regs.rs +38 -0
  98. package/src/rust/softfloat.rs +286 -0
  99. package/src/rust/state_flags.rs +27 -0
  100. package/src/rust/wasmgen/mod.rs +2 -0
  101. package/src/rust/wasmgen/wasm_builder.rs +1047 -0
  102. package/src/rust/wasmgen/wasm_opcodes.rs +221 -0
  103. package/src/rust/zstd.rs +105 -0
  104. package/src/sb16.ts +1928 -0
  105. package/src/state.ts +359 -0
  106. package/src/uart.ts +472 -0
  107. package/src/vga.ts +2791 -0
  108. package/src/virtio.ts +1756 -0
  109. package/src/virtio_balloon.ts +273 -0
  110. package/src/virtio_console.ts +372 -0
  111. package/src/virtio_net.ts +326 -0
@@ -0,0 +1,273 @@
1
+ // https://docs.oasis-open.org/virtio/virtio/v1.2/csd01/virtio-v1.2-csd01.html#x1-2900003
2
+
3
+ import { LOG_PCI } from './const.js'
4
+ import { dbg_log } from './log.js'
5
+ import { VirtIO, VIRTIO_F_VERSION_1 } from './virtio.js'
6
+ import * as marshall from '../lib/marshall.js'
7
+ import { BusConnector } from './bus.js'
8
+
9
+ // Minimal interface for the CPU fields VirtioBalloon needs
10
+ interface VirtioBalloonCPU {
11
+ io: {
12
+ register_read(
13
+ port: number,
14
+ device: object,
15
+ r8?: ((port: number) => number) | undefined,
16
+ r16?: ((port: number) => number) | undefined,
17
+ r32?: ((port: number) => number) | undefined,
18
+ ): void
19
+ register_write(
20
+ port: number,
21
+ device: object,
22
+ w8?: ((port: number) => void) | undefined,
23
+ w16?: ((port: number) => void) | undefined,
24
+ w32?: ((port: number) => void) | undefined,
25
+ ): void
26
+ }
27
+ devices: {
28
+ pci: {
29
+ register_device(device: VirtIO): void
30
+ raise_irq(pci_id: number): void
31
+ lower_irq(pci_id: number): void
32
+ }
33
+ }
34
+ read16(addr: number): number
35
+ read32s(addr: number): number
36
+ write16(addr: number, value: number): void
37
+ write32(addr: number, value: number): void
38
+ read_blob(addr: number, length: number): Uint8Array
39
+ write_blob(blob: Uint8Array, addr: number): void
40
+ zero_memory(addr: number, length: number): void
41
+ memory_size: Int32Array
42
+ }
43
+
44
+ const _VIRTIO_BALLOON_F_MUST_TELL_HOST = 0
45
+ const VIRTIO_BALLOON_F_STATS_VQ = 1
46
+ const _VIRTIO_BALLOON_F_DEFLATE_ON_OOM = 2
47
+ const VIRTIO_BALLOON_F_FREE_PAGE_HINT = 3
48
+
49
+ const STAT_NAMES: string[] = [
50
+ 'SWAP_IN',
51
+ 'SWAP_OUT',
52
+ 'MAJFLT',
53
+ 'MINFLT',
54
+ 'MEMFREE',
55
+ 'MEMTOT',
56
+ 'AVAIL',
57
+ 'CACHES',
58
+ 'HTLB_PGALLOC',
59
+ 'HTLB_PGFAIL',
60
+ ]
61
+
62
+ export class VirtioBalloon {
63
+ bus: BusConnector
64
+ num_pages: number
65
+ actual: number
66
+ fp_cmd: number
67
+ zeroed: number
68
+ virtio: VirtIO
69
+ stats_cb: ((result: Record<string, number>) => void) | null
70
+ free_cb: ((zeroed: number) => void) | null
71
+
72
+ constructor(cpu: VirtioBalloonCPU, bus: BusConnector) {
73
+ this.bus = bus
74
+ this.num_pages = 0
75
+ this.actual = 0
76
+ this.fp_cmd = 0
77
+ this.zeroed = 0
78
+ this.stats_cb = null
79
+ this.free_cb = null
80
+
81
+ const queues = [
82
+ { size_supported: 32, notify_offset: 0 },
83
+ { size_supported: 32, notify_offset: 0 },
84
+ { size_supported: 2, notify_offset: 1 },
85
+ { size_supported: 64, notify_offset: 2 },
86
+ ]
87
+
88
+ //setInterval(() => this.GetStats(console.log.bind(console, "STATS")), 10000);
89
+
90
+ this.virtio = new VirtIO(cpu, {
91
+ name: 'virtio-balloon',
92
+ pci_id: 0x0b << 3,
93
+ device_id: 0x1045,
94
+ subsystem_device_id: 5,
95
+ common: {
96
+ initial_port: 0xd800,
97
+ queues: queues,
98
+ features: [
99
+ VIRTIO_BALLOON_F_STATS_VQ,
100
+ VIRTIO_BALLOON_F_FREE_PAGE_HINT,
101
+ VIRTIO_F_VERSION_1,
102
+ ],
103
+ on_driver_ok: () => {
104
+ dbg_log('Balloon setup', LOG_PCI)
105
+ },
106
+ },
107
+ notification: {
108
+ initial_port: 0xd900,
109
+ single_handler: false,
110
+ handlers: [
111
+ (queue_id: number) => {
112
+ const queue = this.virtio.queues[queue_id]
113
+ while (queue.has_request()) {
114
+ const bufchain = queue.pop_request()
115
+ const buffer = new Uint8Array(
116
+ bufchain.length_readable,
117
+ )
118
+ bufchain.get_next_blob(buffer)
119
+ this.virtio.queues[queue_id].push_reply(bufchain)
120
+ const n = buffer.byteLength / 4
121
+ this.actual += queue_id === 0 ? n : -n
122
+ //console.log(queue_id === 0 ? "Inflate" : "Deflate", this.num_pages, this.actual, bufchain.read_buffers);
123
+ }
124
+ this.virtio.queues[queue_id].flush_replies()
125
+ },
126
+ (queue_id: number) => {
127
+ const queue = this.virtio.queues[queue_id]
128
+ if (queue.has_request()) {
129
+ const bufchain = queue.pop_request()
130
+ const buffer = new Uint8Array(
131
+ bufchain.length_readable,
132
+ )
133
+ bufchain.get_next_blob(buffer)
134
+ const result: Record<string, number> = {}
135
+ for (
136
+ let i = 0;
137
+ i < bufchain.length_readable;
138
+ i += 10
139
+ ) {
140
+ const [cat, value] = marshall.Unmarshall(
141
+ ['h', 'd'],
142
+ buffer,
143
+ { offset: i },
144
+ )
145
+ result[STAT_NAMES[cat]] = value
146
+ }
147
+ this.virtio.queues[queue_id].push_reply(bufchain)
148
+ if (this.stats_cb) this.stats_cb(result)
149
+ }
150
+ },
151
+ (queue_id: number) => {
152
+ const queue = this.virtio.queues[queue_id]
153
+ while (queue.has_request()) {
154
+ const bufchain = queue.pop_request()
155
+ if (bufchain.length_readable > 0) {
156
+ const buffer = new Uint8Array(
157
+ bufchain.length_readable,
158
+ )
159
+ bufchain.get_next_blob(buffer)
160
+ const [cmd] = marshall.Unmarshall(
161
+ ['w'],
162
+ buffer,
163
+ {
164
+ offset: 0,
165
+ },
166
+ )
167
+ if (cmd === 0) {
168
+ if (this.free_cb) this.free_cb(this.zeroed)
169
+ if (this.fp_cmd > 1) this.fp_cmd = 1 // Signal done
170
+ this.virtio.notify_config_changes()
171
+ }
172
+ }
173
+ if (bufchain.length_writable > 0) {
174
+ // console.log("Free pages hinted", bufchain.read_buffers, bufchain.write_buffers);
175
+ for (
176
+ let i = 0;
177
+ i < bufchain.write_buffers.length;
178
+ ++i
179
+ ) {
180
+ const b = bufchain.write_buffers[i]
181
+ this.zeroed += b.len
182
+ this.virtio.cpu.zero_memory(
183
+ b.addr_low,
184
+ b.len,
185
+ )
186
+ }
187
+ }
188
+ this.virtio.queues[queue_id].push_reply(bufchain)
189
+ }
190
+ this.virtio.queues[queue_id].flush_replies()
191
+ },
192
+ ],
193
+ },
194
+ isr_status: {
195
+ initial_port: 0xd700,
196
+ },
197
+ device_specific: {
198
+ initial_port: 0xd600,
199
+ struct: [
200
+ {
201
+ bytes: 4,
202
+ name: 'num_pages',
203
+ read: () => this.num_pages,
204
+ write: (_data: number) => {
205
+ /* read only */
206
+ },
207
+ },
208
+ {
209
+ bytes: 4,
210
+ name: 'actual',
211
+ read: () => {
212
+ return this.actual
213
+ },
214
+ write: (_data: number) => {
215
+ /* read only */
216
+ },
217
+ },
218
+ {
219
+ bytes: 4,
220
+ name: 'free_page_hint_cmd_id',
221
+ read: () => this.fp_cmd,
222
+ write: (_data: number) => {
223
+ /* read only */
224
+ },
225
+ },
226
+ ],
227
+ },
228
+ })
229
+ }
230
+
231
+ Inflate(amount: number): void {
232
+ this.num_pages += amount
233
+ this.virtio.notify_config_changes()
234
+ }
235
+
236
+ Deflate(amount: number): void {
237
+ this.num_pages -= amount
238
+ this.virtio.notify_config_changes()
239
+ }
240
+
241
+ Cleanup(cb: (zeroed: number) => void): void {
242
+ this.fp_cmd = 2
243
+ this.free_cb = cb
244
+ this.zeroed = 0
245
+ this.virtio.notify_config_changes()
246
+ }
247
+
248
+ get_state(): any[] {
249
+ const state: any[] = []
250
+ state[0] = this.virtio
251
+ state[1] = this.num_pages
252
+ state[2] = this.actual
253
+ return state
254
+ }
255
+
256
+ set_state(state: any[]): void {
257
+ this.virtio.set_state(state[0])
258
+ this.num_pages = state[1]
259
+ this.actual = state[2]
260
+ }
261
+
262
+ GetStats(data: (result: Record<string, number>) => void): void {
263
+ this.stats_cb = data
264
+ const queue = this.virtio.queues[2]
265
+ while (queue.has_request()) {
266
+ const bufchain = queue.pop_request()
267
+ this.virtio.queues[2].push_reply(bufchain)
268
+ }
269
+ this.virtio.queues[2].flush_replies()
270
+ }
271
+
272
+ Reset(): void {}
273
+ }
@@ -0,0 +1,372 @@
1
+ import { dbg_assert } from './log.js'
2
+ import { VirtIO, VIRTIO_F_VERSION_1 } from './virtio.js'
3
+ import type { VirtQueueBufferChain } from './virtio.js'
4
+ import * as marshall from '../lib/marshall.js'
5
+ import { BusConnector } from './bus.js'
6
+
7
+ // Minimal interface for the CPU fields VirtioConsole needs
8
+ interface VirtioConsoleCPU {
9
+ io: {
10
+ register_read(
11
+ port: number,
12
+ device: object,
13
+ r8?: ((port: number) => number) | undefined,
14
+ r16?: ((port: number) => number) | undefined,
15
+ r32?: ((port: number) => number) | undefined,
16
+ ): void
17
+ register_write(
18
+ port: number,
19
+ device: object,
20
+ w8?: ((port: number) => void) | undefined,
21
+ w16?: ((port: number) => void) | undefined,
22
+ w32?: ((port: number) => void) | undefined,
23
+ ): void
24
+ }
25
+ devices: {
26
+ pci: {
27
+ register_device(device: VirtIO): void
28
+ raise_irq(pci_id: number): void
29
+ lower_irq(pci_id: number): void
30
+ }
31
+ }
32
+ read16(addr: number): number
33
+ read32s(addr: number): number
34
+ write16(addr: number, value: number): void
35
+ write32(addr: number, value: number): void
36
+ read_blob(addr: number, length: number): Uint8Array
37
+ write_blob(blob: Uint8Array, addr: number): void
38
+ zero_memory(addr: number, length: number): void
39
+ memory_size: Int32Array
40
+ }
41
+
42
+ // https://docs.oasis-open.org/virtio/virtio/v1.2/csd01/virtio-v1.2-csd01.html#x1-2900003
43
+
44
+ const VIRTIO_CONSOLE_DEVICE_READY = 0
45
+ const VIRTIO_CONSOLE_DEVICE_ADD = 1
46
+ const _VIRTIO_CONSOLE_DEVICE_REMOVE = 2
47
+ const VIRTIO_CONSOLE_PORT_READY = 3
48
+ const VIRTIO_CONSOLE_CONSOLE_PORT = 4
49
+ const VIRTIO_CONSOLE_RESIZE = 5
50
+ const VIRTIO_CONSOLE_PORT_OPEN = 6
51
+ const VIRTIO_CONSOLE_PORT_NAME = 7
52
+
53
+ const VIRTIO_CONSOLE_F_SIZE = 0
54
+ const VIRTIO_CONSOLE_F_MULTIPORT = 1
55
+ const _VIRTIO_CONSOLE_F_EMERG_WRITE = 2
56
+
57
+ export class VirtioConsole {
58
+ bus: BusConnector
59
+ rows: number
60
+ cols: number
61
+ ports: number
62
+ virtio: VirtIO
63
+
64
+ constructor(cpu: VirtioConsoleCPU, bus: BusConnector) {
65
+ this.bus = bus
66
+ this.rows = 25
67
+ this.cols = 80
68
+ this.ports = 4
69
+
70
+ const queues = [
71
+ {
72
+ size_supported: 16,
73
+ notify_offset: 0,
74
+ },
75
+ {
76
+ size_supported: 16,
77
+ notify_offset: 1,
78
+ },
79
+ {
80
+ size_supported: 16,
81
+ notify_offset: 2,
82
+ },
83
+ {
84
+ size_supported: 16,
85
+ notify_offset: 3,
86
+ },
87
+ ]
88
+
89
+ for (let i = 1; i < this.ports; ++i) {
90
+ queues.push({ size_supported: 16, notify_offset: 0 })
91
+ queues.push({ size_supported: 8, notify_offset: 1 })
92
+ }
93
+
94
+ this.virtio = new VirtIO(cpu, {
95
+ name: 'virtio-console',
96
+ pci_id: 0x0c << 3,
97
+ device_id: 0x1043,
98
+ subsystem_device_id: 3,
99
+ common: {
100
+ initial_port: 0xb800,
101
+ queues: queues,
102
+ features: [
103
+ VIRTIO_CONSOLE_F_SIZE,
104
+ VIRTIO_CONSOLE_F_MULTIPORT,
105
+ VIRTIO_F_VERSION_1,
106
+ ],
107
+ on_driver_ok: () => {},
108
+ },
109
+ notification: {
110
+ initial_port: 0xb900,
111
+ single_handler: false,
112
+ handlers: [
113
+ (_queue_id: number) => {},
114
+ (queue_id: number) => {
115
+ const queue = this.virtio.queues[queue_id]
116
+ const port = queue_id > 3 ? (queue_id - 3) >> 1 : 0
117
+ while (queue.has_request()) {
118
+ const bufchain = queue.pop_request()
119
+ const buffer = new Uint8Array(
120
+ bufchain.length_readable,
121
+ )
122
+ bufchain.get_next_blob(buffer)
123
+ this.bus.send(
124
+ 'virtio-console' + port + '-output-bytes',
125
+ buffer,
126
+ )
127
+ this.Ack(queue_id, bufchain)
128
+ }
129
+ },
130
+ (queue_id: number) => {
131
+ if (queue_id !== 2) {
132
+ dbg_assert(
133
+ false,
134
+ 'VirtioConsole Notified for wrong queue: ' +
135
+ queue_id +
136
+ ' (expected queue_id of 2)',
137
+ )
138
+ }
139
+ },
140
+ (queue_id: number) => {
141
+ if (queue_id !== 3) {
142
+ dbg_assert(
143
+ false,
144
+ 'VirtioConsole Notified for wrong queue: ' +
145
+ queue_id +
146
+ ' (expected queue_id of 3)',
147
+ )
148
+ return
149
+ }
150
+ const queue = this.virtio.queues[queue_id]
151
+
152
+ while (queue.has_request()) {
153
+ const bufchain = queue.pop_request()
154
+ const buffer = new Uint8Array(
155
+ bufchain.length_readable,
156
+ )
157
+ bufchain.get_next_blob(buffer)
158
+
159
+ const parts = marshall.Unmarshall(
160
+ ['w', 'h', 'h'],
161
+ buffer,
162
+ { offset: 0 },
163
+ )
164
+ const port = parts[0]
165
+ const event = parts[1]
166
+ const _value = parts[2]
167
+
168
+ this.Ack(queue_id, bufchain)
169
+
170
+ switch (event) {
171
+ case VIRTIO_CONSOLE_DEVICE_READY:
172
+ for (let i = 0; i < this.ports; ++i) {
173
+ this.SendEvent(
174
+ i,
175
+ VIRTIO_CONSOLE_DEVICE_ADD,
176
+ 0,
177
+ )
178
+ }
179
+ break
180
+ case VIRTIO_CONSOLE_PORT_READY:
181
+ this.Ack(queue_id, bufchain)
182
+ this.SendEvent(
183
+ port,
184
+ VIRTIO_CONSOLE_CONSOLE_PORT,
185
+ 1,
186
+ )
187
+ this.SendName(port, 'virtio-' + port)
188
+ this.SendEvent(
189
+ port,
190
+ VIRTIO_CONSOLE_PORT_OPEN,
191
+ 1,
192
+ )
193
+
194
+ break
195
+ case VIRTIO_CONSOLE_PORT_OPEN:
196
+ this.Ack(queue_id, bufchain)
197
+ if (port === 0) {
198
+ this.SendWindowSize(port)
199
+ }
200
+ break
201
+ default:
202
+ dbg_assert(
203
+ false,
204
+ ' VirtioConsole received unknown event: ' +
205
+ event,
206
+ )
207
+ return
208
+ }
209
+ }
210
+ },
211
+ ],
212
+ },
213
+ isr_status: {
214
+ initial_port: 0xb700,
215
+ },
216
+ device_specific: {
217
+ initial_port: 0xb600,
218
+ struct: [
219
+ {
220
+ bytes: 2,
221
+ name: 'cols',
222
+ read: () => this.cols,
223
+ write: (_data: number) => {
224
+ /* read only */
225
+ },
226
+ },
227
+ {
228
+ bytes: 2,
229
+ name: 'rows',
230
+ read: () => this.rows,
231
+ write: (_data: number) => {
232
+ /* read only */
233
+ },
234
+ },
235
+ {
236
+ bytes: 4,
237
+ name: 'max_nr_ports',
238
+ read: () => this.ports,
239
+ write: (_data: number) => {
240
+ /* read only */
241
+ },
242
+ },
243
+ {
244
+ bytes: 4,
245
+ name: 'emerg_wr',
246
+ read: () => 0,
247
+ write: (_data: number) => {
248
+ dbg_assert(false, 'Emergency write!')
249
+ },
250
+ },
251
+ ],
252
+ },
253
+ })
254
+
255
+ for (let port = 0; port < this.ports; ++port) {
256
+ const queue_id = port === 0 ? 0 : port * 2 + 2
257
+ this.bus.register(
258
+ 'virtio-console' + port + '-input-bytes',
259
+ function (this: VirtioConsole, data: any) {
260
+ const queue = this.virtio.queues[queue_id]
261
+ if (queue.has_request()) {
262
+ const bufchain = queue.pop_request()
263
+ this.Send(queue_id, bufchain, new Uint8Array(data))
264
+ } else {
265
+ //TODO: Buffer
266
+ }
267
+ },
268
+ this,
269
+ )
270
+
271
+ this.bus.register(
272
+ 'virtio-console' + port + '-resize',
273
+ function (this: VirtioConsole, size: any) {
274
+ if (port === 0) {
275
+ this.cols = size[0]
276
+ this.rows = size[1]
277
+ }
278
+
279
+ if (
280
+ this.virtio.queues[2].is_configured() &&
281
+ this.virtio.queues[2].has_request()
282
+ ) {
283
+ this.SendWindowSize(port, size[0], size[1])
284
+ }
285
+ },
286
+ this,
287
+ )
288
+ }
289
+ }
290
+
291
+ SendWindowSize(
292
+ port: number,
293
+ cols: number | undefined = undefined,
294
+ rows: number | undefined = undefined,
295
+ ): void {
296
+ rows = rows || this.rows
297
+ cols = cols || this.cols
298
+ const bufchain = this.virtio.queues[2].pop_request()
299
+ const buf = new Uint8Array(12)
300
+ marshall.Marshall(
301
+ ['w', 'h', 'h', 'h', 'h'],
302
+ [port, VIRTIO_CONSOLE_RESIZE, 0, rows, cols],
303
+ buf,
304
+ 0,
305
+ )
306
+ this.Send(2, bufchain, buf)
307
+ }
308
+
309
+ SendName(port: number, name: string): void {
310
+ const bufchain = this.virtio.queues[2].pop_request()
311
+ const namex = new TextEncoder().encode(name)
312
+ const buf = new Uint8Array(8 + namex.length + 1)
313
+ marshall.Marshall(
314
+ ['w', 'h', 'h'],
315
+ [port, VIRTIO_CONSOLE_PORT_NAME, 1],
316
+ buf,
317
+ 0,
318
+ )
319
+ for (let i = 0; i < namex.length; ++i) {
320
+ buf[i + 8] = namex[i]
321
+ }
322
+ buf[8 + namex.length] = 0
323
+ this.Send(2, bufchain, buf)
324
+ }
325
+
326
+ get_state(): any[] {
327
+ const state: any[] = []
328
+
329
+ state[0] = this.virtio
330
+ state[1] = this.rows
331
+ state[2] = this.cols
332
+ state[3] = this.ports
333
+
334
+ return state
335
+ }
336
+
337
+ set_state(state: any[]): void {
338
+ this.virtio.set_state(state[0])
339
+ this.rows = state[1]
340
+ this.cols = state[2]
341
+ this.ports = state[3]
342
+ }
343
+
344
+ reset(): void {
345
+ this.virtio.reset()
346
+ }
347
+
348
+ SendEvent(port: number, event: number, value: number): void {
349
+ const queue = this.virtio.queues[2]
350
+ const bufchain = queue.pop_request()
351
+
352
+ const buf = new Uint8Array(8)
353
+ marshall.Marshall(['w', 'h', 'h'], [port, event, value], buf, 0)
354
+ this.Send(2, bufchain, buf)
355
+ }
356
+
357
+ Send(
358
+ queue_id: number,
359
+ bufchain: VirtQueueBufferChain,
360
+ blob: Uint8Array,
361
+ ): void {
362
+ bufchain.set_next_blob(blob)
363
+ this.virtio.queues[queue_id].push_reply(bufchain)
364
+ this.virtio.queues[queue_id].flush_replies()
365
+ }
366
+
367
+ Ack(queue_id: number, bufchain: VirtQueueBufferChain): void {
368
+ bufchain.set_next_blob(new Uint8Array(0))
369
+ this.virtio.queues[queue_id].push_reply(bufchain)
370
+ this.virtio.queues[queue_id].flush_replies()
371
+ }
372
+ }