-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathbuild_apptable.py
More file actions
executable file
·111 lines (90 loc) · 3.68 KB
/
build_apptable.py
File metadata and controls
executable file
·111 lines (90 loc) · 3.68 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
#!/usr/bin/env python3
"""
Build app table for Rix
Creates an app table with headers and concatenated app binaries
"""
import struct
import sys
import os
APP_MAGIC = 0x4150505F # "APP_"
APP_VERSION = 1
APP_FLAG_USERMODE = 0x01
def create_app_table(app_files, output_file):
"""Create app table from list of app binaries"""
apps = []
usermode_flags = []
# Parse arguments - look for --usermode flags
i = 0
while i < len(app_files):
if app_files[i] == '--usermode':
# Next file is a user mode app
i += 1
if i >= len(app_files):
print("Error: --usermode flag requires an app file")
sys.exit(1)
usermode_flags.append(True)
app_file = app_files[i]
else:
usermode_flags.append(False)
app_file = app_files[i]
if not os.path.exists(app_file):
print(f"Error: App file not found: {app_file}")
sys.exit(1)
with open(app_file, 'rb') as f:
data = f.read()
# Extract app name from filename (without path and extension)
name = os.path.splitext(os.path.basename(app_file))[0]
is_usermode = usermode_flags[-1]
apps.append({
'name': name,
'data': data,
'size': len(data),
'usermode': is_usermode
})
mode_str = "usermode" if is_usermode else "kernel"
print(f"Added app: {name} ({len(data)} bytes, {mode_str})")
i += 1
# Calculate offsets
offset = 0
for app in apps:
app['offset'] = offset
offset += app['size']
# Write app table
with open(output_file, 'wb') as f:
# Write table header (16 bytes)
f.write(struct.pack('<I', APP_MAGIC)) # magic
f.write(struct.pack('<I', APP_VERSION)) # version
f.write(struct.pack('<I', len(apps))) # num_apps
f.write(struct.pack('<I', 0)) # reserved
# Write app headers (80 bytes each - matching Rust AppHeader struct)
for app in apps:
# Pad name to 64 bytes (matching Rust struct)
name_bytes = app['name'].encode('ascii')[:63]
name_padded = name_bytes + b'\x00' * (64 - len(name_bytes))
flags = APP_FLAG_USERMODE if app['usermode'] else 0
f.write(name_padded) # name[64]
f.write(struct.pack('<I', app['size'])) # size
f.write(struct.pack('<I', app['offset'])) # offset
f.write(struct.pack('<I', 0)) # entry_offset (entry is at start)
f.write(struct.pack('<I', flags)) # flags
# Pad to 16-byte alignment for app data (SSE instructions require this)
current_pos = f.tell()
padding_needed = (16 - (current_pos % 16)) % 16
if padding_needed > 0:
f.write(b'\x00' * padding_needed)
print(f"Added {padding_needed} bytes padding for alignment")
# Write app data
for app in apps:
f.write(app['data'])
total_size = os.path.getsize(output_file)
print(f"\nApp table created: {output_file}")
print(f"Total size: {total_size} bytes")
print(f"Apps: {len(apps)}")
if __name__ == '__main__':
if len(sys.argv) < 3:
print("Usage: build_apptable.py <output_file> [--usermode] <app1.bin> [--usermode] [app2.bin ...]")
print(" --usermode flag marks the following app as a user mode app")
sys.exit(1)
output_file = sys.argv[1]
app_files = sys.argv[2:]
create_app_table(app_files, output_file)