pyOS-kernel 0.1.0__py3-none-any.whl
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.
- pyos/__init__.py +22 -0
- pyos/boot/__init__.py +3 -0
- pyos/boot/bootloader.asm +174 -0
- pyos/builder.py +177 -0
- pyos/cli.py +286 -0
- pyos/compiler/__init__.py +8 -0
- pyos/compiler/assembler.py +180 -0
- pyos/compiler/codegen.py +238 -0
- pyos/drivers/__init__.py +8 -0
- pyos/drivers/keyboard.py +319 -0
- pyos/drivers/screen.py +310 -0
- pyos/emulator.py +195 -0
- pyos/interrupts/__init__.py +8 -0
- pyos/interrupts/handler.py +237 -0
- pyos/interrupts/idt.py +165 -0
- pyos/kernel.py +288 -0
- pyos/memory/__init__.py +8 -0
- pyos/memory/gdt.py +295 -0
- pyos/memory/manager.py +397 -0
- pyos/syscalls/__init__.py +7 -0
- pyos/syscalls/handler.py +179 -0
- pyos_kernel-0.1.0.dist-info/METADATA +323 -0
- pyos_kernel-0.1.0.dist-info/RECORD +27 -0
- pyos_kernel-0.1.0.dist-info/WHEEL +5 -0
- pyos_kernel-0.1.0.dist-info/entry_points.txt +2 -0
- pyos_kernel-0.1.0.dist-info/licenses/LICENSE +21 -0
- pyos_kernel-0.1.0.dist-info/top_level.txt +1 -0
pyos/memory/manager.py
ADDED
|
@@ -0,0 +1,397 @@
|
|
|
1
|
+
"""
|
|
2
|
+
pyOS Memory Manager - Static and Dynamic Memory Allocation
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from typing import Optional, Dict, List, Tuple
|
|
6
|
+
from dataclasses import dataclass
|
|
7
|
+
from enum import Enum
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class AllocationType(Enum):
|
|
11
|
+
"""Memory allocation types"""
|
|
12
|
+
STATIC = "static"
|
|
13
|
+
DYNAMIC = "dynamic"
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@dataclass
|
|
17
|
+
class MemoryBlock:
|
|
18
|
+
"""Represents a memory block"""
|
|
19
|
+
address: int
|
|
20
|
+
size: int
|
|
21
|
+
used: bool = False
|
|
22
|
+
name: Optional[str] = None
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
@dataclass
|
|
26
|
+
class MemoryRegion:
|
|
27
|
+
"""Represents a memory region"""
|
|
28
|
+
start: int
|
|
29
|
+
end: int
|
|
30
|
+
name: str
|
|
31
|
+
writable: bool = True
|
|
32
|
+
executable: bool = False
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class Memory:
|
|
36
|
+
"""
|
|
37
|
+
Memory Manager for pyOS.
|
|
38
|
+
|
|
39
|
+
Provides both static and dynamic memory allocation.
|
|
40
|
+
|
|
41
|
+
Example:
|
|
42
|
+
# Static allocation
|
|
43
|
+
buffer = Memory.allocate_static(1024, name="my_buffer")
|
|
44
|
+
|
|
45
|
+
# Dynamic allocation (heap)
|
|
46
|
+
ptr = Memory.malloc(256)
|
|
47
|
+
Memory.free(ptr)
|
|
48
|
+
"""
|
|
49
|
+
|
|
50
|
+
# Memory layout constants
|
|
51
|
+
KERNEL_START = 0x100000 # 1MB - Kernel starts here
|
|
52
|
+
KERNEL_SIZE = 0x100000 # 1MB for kernel
|
|
53
|
+
HEAP_START = 0x200000 # 2MB - Heap starts here
|
|
54
|
+
HEAP_SIZE = 0x1000000 # 16MB heap
|
|
55
|
+
STACK_TOP = 0x90000 # Stack top (grows down)
|
|
56
|
+
STACK_SIZE = 0x10000 # 64KB stack
|
|
57
|
+
VGA_ADDRESS = 0xB8000 # VGA text buffer
|
|
58
|
+
|
|
59
|
+
_static_allocations: List[MemoryBlock] = []
|
|
60
|
+
_heap_blocks: List[MemoryBlock] = []
|
|
61
|
+
_next_static_address: int = KERNEL_START + KERNEL_SIZE
|
|
62
|
+
_heap_initialized: bool = False
|
|
63
|
+
_operations: list = []
|
|
64
|
+
|
|
65
|
+
@classmethod
|
|
66
|
+
def allocate_static(cls, size: int, name: Optional[str] = None, align: int = 4) -> int:
|
|
67
|
+
"""
|
|
68
|
+
Allocate static memory (compile-time allocation).
|
|
69
|
+
|
|
70
|
+
Args:
|
|
71
|
+
size: Size in bytes
|
|
72
|
+
name: Optional name for the allocation
|
|
73
|
+
align: Alignment in bytes (default: 4)
|
|
74
|
+
|
|
75
|
+
Returns:
|
|
76
|
+
The allocated address.
|
|
77
|
+
|
|
78
|
+
Example:
|
|
79
|
+
buffer_addr = Memory.allocate_static(1024, name="screen_buffer")
|
|
80
|
+
"""
|
|
81
|
+
# Align address
|
|
82
|
+
if cls._next_static_address % align != 0:
|
|
83
|
+
cls._next_static_address += align - (cls._next_static_address % align)
|
|
84
|
+
|
|
85
|
+
address = cls._next_static_address
|
|
86
|
+
cls._next_static_address += size
|
|
87
|
+
|
|
88
|
+
block = MemoryBlock(
|
|
89
|
+
address=address,
|
|
90
|
+
size=size,
|
|
91
|
+
used=True,
|
|
92
|
+
name=name,
|
|
93
|
+
)
|
|
94
|
+
cls._static_allocations.append(block)
|
|
95
|
+
|
|
96
|
+
cls._operations.append({
|
|
97
|
+
"type": "allocate_static",
|
|
98
|
+
"address": address,
|
|
99
|
+
"size": size,
|
|
100
|
+
"name": name,
|
|
101
|
+
})
|
|
102
|
+
|
|
103
|
+
return address
|
|
104
|
+
|
|
105
|
+
@classmethod
|
|
106
|
+
def malloc(cls, size: int) -> int:
|
|
107
|
+
"""
|
|
108
|
+
Allocate dynamic memory from heap.
|
|
109
|
+
|
|
110
|
+
Args:
|
|
111
|
+
size: Size in bytes
|
|
112
|
+
|
|
113
|
+
Returns:
|
|
114
|
+
Pointer to allocated memory, or 0 if failed.
|
|
115
|
+
|
|
116
|
+
Example:
|
|
117
|
+
ptr = Memory.malloc(256)
|
|
118
|
+
if ptr:
|
|
119
|
+
# Use memory
|
|
120
|
+
Memory.free(ptr)
|
|
121
|
+
"""
|
|
122
|
+
cls._operations.append({
|
|
123
|
+
"type": "malloc",
|
|
124
|
+
"size": size,
|
|
125
|
+
})
|
|
126
|
+
|
|
127
|
+
# Find free block (first-fit algorithm)
|
|
128
|
+
for block in cls._heap_blocks:
|
|
129
|
+
if not block.used and block.size >= size:
|
|
130
|
+
# Split block if much larger
|
|
131
|
+
if block.size > size + 32:
|
|
132
|
+
new_block = MemoryBlock(
|
|
133
|
+
address=block.address + size,
|
|
134
|
+
size=block.size - size,
|
|
135
|
+
used=False,
|
|
136
|
+
)
|
|
137
|
+
cls._heap_blocks.append(new_block)
|
|
138
|
+
block.size = size
|
|
139
|
+
|
|
140
|
+
block.used = True
|
|
141
|
+
return block.address
|
|
142
|
+
|
|
143
|
+
# No free block found, allocate new
|
|
144
|
+
if cls._heap_blocks:
|
|
145
|
+
last = max(cls._heap_blocks, key=lambda b: b.address)
|
|
146
|
+
new_address = last.address + last.size
|
|
147
|
+
else:
|
|
148
|
+
new_address = cls.HEAP_START
|
|
149
|
+
|
|
150
|
+
if new_address + size > cls.HEAP_START + cls.HEAP_SIZE:
|
|
151
|
+
return 0 # Out of memory
|
|
152
|
+
|
|
153
|
+
block = MemoryBlock(address=new_address, size=size, used=True)
|
|
154
|
+
cls._heap_blocks.append(block)
|
|
155
|
+
return new_address
|
|
156
|
+
|
|
157
|
+
@classmethod
|
|
158
|
+
def free(cls, address: int) -> bool:
|
|
159
|
+
"""
|
|
160
|
+
Free dynamically allocated memory.
|
|
161
|
+
|
|
162
|
+
Args:
|
|
163
|
+
address: Pointer returned by malloc
|
|
164
|
+
|
|
165
|
+
Returns:
|
|
166
|
+
True if freed successfully.
|
|
167
|
+
|
|
168
|
+
Example:
|
|
169
|
+
Memory.free(ptr)
|
|
170
|
+
"""
|
|
171
|
+
cls._operations.append({
|
|
172
|
+
"type": "free",
|
|
173
|
+
"address": address,
|
|
174
|
+
})
|
|
175
|
+
|
|
176
|
+
for block in cls._heap_blocks:
|
|
177
|
+
if block.address == address:
|
|
178
|
+
block.used = False
|
|
179
|
+
cls._coalesce_free_blocks()
|
|
180
|
+
return True
|
|
181
|
+
return False
|
|
182
|
+
|
|
183
|
+
@classmethod
|
|
184
|
+
def _coalesce_free_blocks(cls) -> None:
|
|
185
|
+
"""Merge adjacent free blocks."""
|
|
186
|
+
cls._heap_blocks.sort(key=lambda b: b.address)
|
|
187
|
+
|
|
188
|
+
i = 0
|
|
189
|
+
while i < len(cls._heap_blocks) - 1:
|
|
190
|
+
current = cls._heap_blocks[i]
|
|
191
|
+
next_block = cls._heap_blocks[i + 1]
|
|
192
|
+
|
|
193
|
+
if not current.used and not next_block.used:
|
|
194
|
+
if current.address + current.size == next_block.address:
|
|
195
|
+
current.size += next_block.size
|
|
196
|
+
cls._heap_blocks.pop(i + 1)
|
|
197
|
+
continue
|
|
198
|
+
i += 1
|
|
199
|
+
|
|
200
|
+
@classmethod
|
|
201
|
+
def realloc(cls, address: int, new_size: int) -> int:
|
|
202
|
+
"""
|
|
203
|
+
Reallocate memory with new size.
|
|
204
|
+
|
|
205
|
+
Args:
|
|
206
|
+
address: Existing pointer
|
|
207
|
+
new_size: New size in bytes
|
|
208
|
+
|
|
209
|
+
Returns:
|
|
210
|
+
New pointer (may be different from original).
|
|
211
|
+
"""
|
|
212
|
+
cls._operations.append({
|
|
213
|
+
"type": "realloc",
|
|
214
|
+
"address": address,
|
|
215
|
+
"new_size": new_size,
|
|
216
|
+
})
|
|
217
|
+
|
|
218
|
+
# Find existing block
|
|
219
|
+
for block in cls._heap_blocks:
|
|
220
|
+
if block.address == address:
|
|
221
|
+
if block.size >= new_size:
|
|
222
|
+
return address # Already big enough
|
|
223
|
+
|
|
224
|
+
# Allocate new, copy, free old
|
|
225
|
+
new_ptr = cls.malloc(new_size)
|
|
226
|
+
if new_ptr:
|
|
227
|
+
cls.free(address)
|
|
228
|
+
return new_ptr
|
|
229
|
+
|
|
230
|
+
return cls.malloc(new_size)
|
|
231
|
+
|
|
232
|
+
@classmethod
|
|
233
|
+
def calloc(cls, count: int, size: int) -> int:
|
|
234
|
+
"""
|
|
235
|
+
Allocate and zero-initialize memory.
|
|
236
|
+
|
|
237
|
+
Args:
|
|
238
|
+
count: Number of elements
|
|
239
|
+
size: Size of each element
|
|
240
|
+
|
|
241
|
+
Returns:
|
|
242
|
+
Pointer to zeroed memory.
|
|
243
|
+
|
|
244
|
+
Example:
|
|
245
|
+
array = Memory.calloc(100, 4) # 100 integers
|
|
246
|
+
"""
|
|
247
|
+
total = count * size
|
|
248
|
+
cls._operations.append({
|
|
249
|
+
"type": "calloc",
|
|
250
|
+
"count": count,
|
|
251
|
+
"size": size,
|
|
252
|
+
})
|
|
253
|
+
return cls.malloc(total)
|
|
254
|
+
|
|
255
|
+
@classmethod
|
|
256
|
+
def memset(cls, address: int, value: int, size: int) -> None:
|
|
257
|
+
"""
|
|
258
|
+
Fill memory with a value.
|
|
259
|
+
|
|
260
|
+
Args:
|
|
261
|
+
address: Start address
|
|
262
|
+
value: Byte value to fill
|
|
263
|
+
size: Number of bytes
|
|
264
|
+
|
|
265
|
+
Example:
|
|
266
|
+
Memory.memset(buffer, 0, 1024) # Zero out buffer
|
|
267
|
+
"""
|
|
268
|
+
cls._operations.append({
|
|
269
|
+
"type": "memset",
|
|
270
|
+
"address": address,
|
|
271
|
+
"value": value,
|
|
272
|
+
"size": size,
|
|
273
|
+
})
|
|
274
|
+
|
|
275
|
+
@classmethod
|
|
276
|
+
def memcpy(cls, dest: int, src: int, size: int) -> None:
|
|
277
|
+
"""
|
|
278
|
+
Copy memory from source to destination.
|
|
279
|
+
|
|
280
|
+
Args:
|
|
281
|
+
dest: Destination address
|
|
282
|
+
src: Source address
|
|
283
|
+
size: Number of bytes to copy
|
|
284
|
+
|
|
285
|
+
Example:
|
|
286
|
+
Memory.memcpy(dest_buffer, src_buffer, 256)
|
|
287
|
+
"""
|
|
288
|
+
cls._operations.append({
|
|
289
|
+
"type": "memcpy",
|
|
290
|
+
"dest": dest,
|
|
291
|
+
"src": src,
|
|
292
|
+
"size": size,
|
|
293
|
+
})
|
|
294
|
+
|
|
295
|
+
@classmethod
|
|
296
|
+
def read_byte(cls, address: int) -> int:
|
|
297
|
+
"""
|
|
298
|
+
Read a byte from memory.
|
|
299
|
+
|
|
300
|
+
Args:
|
|
301
|
+
address: Memory address
|
|
302
|
+
|
|
303
|
+
Returns:
|
|
304
|
+
Byte value (0-255).
|
|
305
|
+
"""
|
|
306
|
+
cls._operations.append({
|
|
307
|
+
"type": "read_byte",
|
|
308
|
+
"address": address,
|
|
309
|
+
})
|
|
310
|
+
return 0
|
|
311
|
+
|
|
312
|
+
@classmethod
|
|
313
|
+
def write_byte(cls, address: int, value: int) -> None:
|
|
314
|
+
"""
|
|
315
|
+
Write a byte to memory.
|
|
316
|
+
|
|
317
|
+
Args:
|
|
318
|
+
address: Memory address
|
|
319
|
+
value: Byte value (0-255)
|
|
320
|
+
"""
|
|
321
|
+
cls._operations.append({
|
|
322
|
+
"type": "write_byte",
|
|
323
|
+
"address": address,
|
|
324
|
+
"value": value & 0xFF,
|
|
325
|
+
})
|
|
326
|
+
|
|
327
|
+
@classmethod
|
|
328
|
+
def read_word(cls, address: int) -> int:
|
|
329
|
+
"""Read a 16-bit word from memory."""
|
|
330
|
+
cls._operations.append({"type": "read_word", "address": address})
|
|
331
|
+
return 0
|
|
332
|
+
|
|
333
|
+
@classmethod
|
|
334
|
+
def write_word(cls, address: int, value: int) -> None:
|
|
335
|
+
"""Write a 16-bit word to memory."""
|
|
336
|
+
cls._operations.append({
|
|
337
|
+
"type": "write_word",
|
|
338
|
+
"address": address,
|
|
339
|
+
"value": value & 0xFFFF,
|
|
340
|
+
})
|
|
341
|
+
|
|
342
|
+
@classmethod
|
|
343
|
+
def read_dword(cls, address: int) -> int:
|
|
344
|
+
"""Read a 32-bit dword from memory."""
|
|
345
|
+
cls._operations.append({"type": "read_dword", "address": address})
|
|
346
|
+
return 0
|
|
347
|
+
|
|
348
|
+
@classmethod
|
|
349
|
+
def write_dword(cls, address: int, value: int) -> None:
|
|
350
|
+
"""Write a 32-bit dword to memory."""
|
|
351
|
+
cls._operations.append({
|
|
352
|
+
"type": "write_dword",
|
|
353
|
+
"address": address,
|
|
354
|
+
"value": value & 0xFFFFFFFF,
|
|
355
|
+
})
|
|
356
|
+
|
|
357
|
+
@classmethod
|
|
358
|
+
def get_free_memory(cls) -> int:
|
|
359
|
+
"""Get total free heap memory."""
|
|
360
|
+
used = sum(b.size for b in cls._heap_blocks if b.used)
|
|
361
|
+
return cls.HEAP_SIZE - used
|
|
362
|
+
|
|
363
|
+
@classmethod
|
|
364
|
+
def get_used_memory(cls) -> int:
|
|
365
|
+
"""Get total used heap memory."""
|
|
366
|
+
return sum(b.size for b in cls._heap_blocks if b.used)
|
|
367
|
+
|
|
368
|
+
@classmethod
|
|
369
|
+
def get_memory_map(cls) -> List[MemoryRegion]:
|
|
370
|
+
"""
|
|
371
|
+
Get the memory map.
|
|
372
|
+
|
|
373
|
+
Returns:
|
|
374
|
+
List of memory regions.
|
|
375
|
+
"""
|
|
376
|
+
return [
|
|
377
|
+
MemoryRegion(0x0, 0x500, "Real Mode IVT/BDA", writable=False),
|
|
378
|
+
MemoryRegion(0x7C00, 0x7E00, "Bootloader", executable=True),
|
|
379
|
+
MemoryRegion(cls.STACK_TOP - cls.STACK_SIZE, cls.STACK_TOP, "Stack"),
|
|
380
|
+
MemoryRegion(cls.VGA_ADDRESS, cls.VGA_ADDRESS + 0x8000, "VGA Buffer"),
|
|
381
|
+
MemoryRegion(cls.KERNEL_START, cls.KERNEL_START + cls.KERNEL_SIZE, "Kernel", executable=True),
|
|
382
|
+
MemoryRegion(cls.HEAP_START, cls.HEAP_START + cls.HEAP_SIZE, "Heap"),
|
|
383
|
+
]
|
|
384
|
+
|
|
385
|
+
@classmethod
|
|
386
|
+
def _reset(cls) -> None:
|
|
387
|
+
"""Reset memory state (used internally)."""
|
|
388
|
+
cls._static_allocations = []
|
|
389
|
+
cls._heap_blocks = []
|
|
390
|
+
cls._next_static_address = cls.KERNEL_START + cls.KERNEL_SIZE
|
|
391
|
+
cls._heap_initialized = False
|
|
392
|
+
cls._operations = []
|
|
393
|
+
|
|
394
|
+
@classmethod
|
|
395
|
+
def _get_operations(cls) -> list:
|
|
396
|
+
"""Get all recorded operations (used by compiler)."""
|
|
397
|
+
return cls._operations.copy()
|
pyos/syscalls/handler.py
ADDED
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
"""
|
|
2
|
+
pyOS System Call Handler
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from typing import Callable, Dict, Optional, Any
|
|
6
|
+
from dataclasses import dataclass
|
|
7
|
+
from enum import Enum
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class SysCallNumber(Enum):
|
|
11
|
+
"""Standard system call numbers"""
|
|
12
|
+
SYS_EXIT = 1
|
|
13
|
+
SYS_READ = 3
|
|
14
|
+
SYS_WRITE = 4
|
|
15
|
+
SYS_OPEN = 5
|
|
16
|
+
SYS_CLOSE = 6
|
|
17
|
+
SYS_GETPID = 20
|
|
18
|
+
SYS_MALLOC = 90
|
|
19
|
+
SYS_FREE = 91
|
|
20
|
+
SYS_SLEEP = 162
|
|
21
|
+
SYS_TIME = 201
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
@dataclass
|
|
25
|
+
class SysCallContext:
|
|
26
|
+
"""Context passed to system call handlers"""
|
|
27
|
+
syscall_number: int
|
|
28
|
+
arg1: int = 0
|
|
29
|
+
arg2: int = 0
|
|
30
|
+
arg3: int = 0
|
|
31
|
+
arg4: int = 0
|
|
32
|
+
arg5: int = 0
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class SysCall:
|
|
36
|
+
"""
|
|
37
|
+
System Call Manager.
|
|
38
|
+
|
|
39
|
+
Provides methods to define and handle system calls.
|
|
40
|
+
|
|
41
|
+
Example:
|
|
42
|
+
@SysCall.handler(SysCallNumber.SYS_WRITE)
|
|
43
|
+
def sys_write(ctx):
|
|
44
|
+
fd = ctx.arg1
|
|
45
|
+
buf = ctx.arg2
|
|
46
|
+
count = ctx.arg3
|
|
47
|
+
# Write implementation
|
|
48
|
+
return count
|
|
49
|
+
"""
|
|
50
|
+
|
|
51
|
+
_handlers: Dict[int, Callable] = {}
|
|
52
|
+
_operations: list = []
|
|
53
|
+
|
|
54
|
+
@classmethod
|
|
55
|
+
def handler(cls, syscall: SysCallNumber):
|
|
56
|
+
"""
|
|
57
|
+
Decorator to register a system call handler.
|
|
58
|
+
|
|
59
|
+
Args:
|
|
60
|
+
syscall: The system call number
|
|
61
|
+
|
|
62
|
+
Example:
|
|
63
|
+
@SysCall.handler(SysCallNumber.SYS_EXIT)
|
|
64
|
+
def sys_exit(ctx):
|
|
65
|
+
# Exit implementation
|
|
66
|
+
pass
|
|
67
|
+
"""
|
|
68
|
+
def decorator(func: Callable) -> Callable:
|
|
69
|
+
cls._handlers[syscall.value] = func
|
|
70
|
+
cls._operations.append({
|
|
71
|
+
"type": "register_handler",
|
|
72
|
+
"syscall": syscall.value,
|
|
73
|
+
"name": func.__name__,
|
|
74
|
+
})
|
|
75
|
+
return func
|
|
76
|
+
return decorator
|
|
77
|
+
|
|
78
|
+
@classmethod
|
|
79
|
+
def register(cls, syscall_number: int, handler: Callable) -> None:
|
|
80
|
+
"""
|
|
81
|
+
Register a system call handler by number.
|
|
82
|
+
|
|
83
|
+
Args:
|
|
84
|
+
syscall_number: System call number
|
|
85
|
+
handler: Handler function
|
|
86
|
+
|
|
87
|
+
Example:
|
|
88
|
+
def my_syscall(ctx):
|
|
89
|
+
return 0
|
|
90
|
+
SysCall.register(100, my_syscall)
|
|
91
|
+
"""
|
|
92
|
+
cls._handlers[syscall_number] = handler
|
|
93
|
+
cls._operations.append({
|
|
94
|
+
"type": "register_handler",
|
|
95
|
+
"syscall": syscall_number,
|
|
96
|
+
"name": handler.__name__,
|
|
97
|
+
})
|
|
98
|
+
|
|
99
|
+
@classmethod
|
|
100
|
+
def call(cls, syscall_number: int, *args) -> int:
|
|
101
|
+
"""
|
|
102
|
+
Invoke a system call.
|
|
103
|
+
|
|
104
|
+
Args:
|
|
105
|
+
syscall_number: System call number
|
|
106
|
+
*args: Arguments to pass
|
|
107
|
+
|
|
108
|
+
Returns:
|
|
109
|
+
Return value from syscall.
|
|
110
|
+
|
|
111
|
+
Example:
|
|
112
|
+
result = SysCall.call(SysCallNumber.SYS_WRITE.value, 1, buffer, length)
|
|
113
|
+
"""
|
|
114
|
+
cls._operations.append({
|
|
115
|
+
"type": "call",
|
|
116
|
+
"syscall": syscall_number,
|
|
117
|
+
"args": args,
|
|
118
|
+
})
|
|
119
|
+
|
|
120
|
+
handler = cls._handlers.get(syscall_number)
|
|
121
|
+
if handler:
|
|
122
|
+
ctx = SysCallContext(
|
|
123
|
+
syscall_number=syscall_number,
|
|
124
|
+
arg1=args[0] if len(args) > 0 else 0,
|
|
125
|
+
arg2=args[1] if len(args) > 1 else 0,
|
|
126
|
+
arg3=args[2] if len(args) > 2 else 0,
|
|
127
|
+
arg4=args[3] if len(args) > 3 else 0,
|
|
128
|
+
arg5=args[4] if len(args) > 4 else 0,
|
|
129
|
+
)
|
|
130
|
+
return handler(ctx)
|
|
131
|
+
return -1
|
|
132
|
+
|
|
133
|
+
@classmethod
|
|
134
|
+
def exit(cls, code: int = 0) -> None:
|
|
135
|
+
"""
|
|
136
|
+
Exit the current process.
|
|
137
|
+
|
|
138
|
+
Args:
|
|
139
|
+
code: Exit code (default: 0)
|
|
140
|
+
"""
|
|
141
|
+
cls._operations.append({
|
|
142
|
+
"type": "exit",
|
|
143
|
+
"code": code,
|
|
144
|
+
})
|
|
145
|
+
|
|
146
|
+
@classmethod
|
|
147
|
+
def sleep(cls, milliseconds: int) -> None:
|
|
148
|
+
"""
|
|
149
|
+
Sleep for specified milliseconds.
|
|
150
|
+
|
|
151
|
+
Args:
|
|
152
|
+
milliseconds: Time to sleep
|
|
153
|
+
"""
|
|
154
|
+
cls._operations.append({
|
|
155
|
+
"type": "sleep",
|
|
156
|
+
"ms": milliseconds,
|
|
157
|
+
})
|
|
158
|
+
|
|
159
|
+
@classmethod
|
|
160
|
+
def get_time(cls) -> int:
|
|
161
|
+
"""
|
|
162
|
+
Get current system time.
|
|
163
|
+
|
|
164
|
+
Returns:
|
|
165
|
+
Time in milliseconds since boot.
|
|
166
|
+
"""
|
|
167
|
+
cls._operations.append({"type": "get_time"})
|
|
168
|
+
return 0
|
|
169
|
+
|
|
170
|
+
@classmethod
|
|
171
|
+
def _reset(cls) -> None:
|
|
172
|
+
"""Reset syscall state (used internally)."""
|
|
173
|
+
cls._handlers = {}
|
|
174
|
+
cls._operations = []
|
|
175
|
+
|
|
176
|
+
@classmethod
|
|
177
|
+
def _get_operations(cls) -> list:
|
|
178
|
+
"""Get all recorded operations (used by compiler)."""
|
|
179
|
+
return cls._operations.copy()
|