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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
|
# Ghidra script to analyze GSP .fwimage binary
# Usage: analyzeHeadless ... -postScript analyze_gsp_fwimage.py
import sys
import os
import json
# Get the current program
program = getCurrentProgram()
listing = program.getListing()
memory = program.getMemory()
function_manager = program.getFunctionManager()
print("=== GSP Firmware .fwimage Analysis ===")
print(f"Program: {program.getName()}")
print(f"Architecture: {program.getLanguage().toString()}")
# Create output directory
output_dir = "/home/rmcore/Git/integdev_gpu_drv/open-iov/firmware/570-GSP"
os.makedirs(output_dir, exist_ok=True)
# 1. Find all functions
print("\n--- Finding Functions ---")
functions = []
func_iter = function_manager.getFunctions(True)
while func_iter.hasNext():
func = func_iter.next()
functions.append({
"name": func.getName(),
"entry": str(func.getEntryPoint()),
"size": func.getBody().getNumAddresses(),
"signature": func.getSignature().toString() if func.getSignature() else ""
})
print(f"Found {len(functions)} functions")
# Save function list
with open(os.path.join(output_dir, "functions.json"), "w") as f:
json.dump(functions, f, indent=2)
# 2. Find RPC-related functions (vRPC/pRPC handlers)
print("\n--- Finding RPC Handlers ---")
rpc_keywords = [
"rpc", "Rpc", "RPC",
"vgpu", "Vgpu", "VGPU",
"vmiop", "Vmiop", "VMIOP",
"hal", "Hal", "HAL",
"bar", "Bar", "BAR",
"migrate", "Migrate", "MIGRATE",
"init", "Init", "INIT",
"boot", "Boot", "BOOT",
"kgsp", "Kgsp", "KGSP"
]
rpc_functions = []
for func in functions:
name_lower = func["name"].lower()
for kw in rpc_keywords:
if kw.lower() in name_lower:
rpc_functions.append(func)
break
print(f"Found {len(rpc_functions)} potential RPC-related functions")
with open(os.path.join(output_dir, "rpc_functions.json"), "w") as f:
json.dump(rpc_functions, f, indent=2)
# 3. Find strings related to vGPU initialization
print("\n--- Finding vGPU-related Strings ---")
vgpu_strings = []
string_iter = listing.getDefinedData(True)
while string_iter.hasNext():
data = string_iter.next()
if data.getDataType().getName() == "string":
value = data.getValue()
if value:
val_str = str(value).lower()
if any(kw in val_str for kw in ["vgpu", "vmiop", "rpc", "hal", "bar", "migrate", "init", "boot", "kgsp", "wpr", "firmware", "version"]):
vgpu_strings.append({
"address": str(data.getAddress()),
"value": str(value)
})
print(f"Found {len(vgpu_strings)} vGPU-related strings")
with open(os.path.join(output_dir, "vgpu_strings.json"), "w") as f:
json.dump(vgpu_strings, f, indent=2)
# 4. Find entry points and initialization functions
print("\n--- Finding Entry Points ---")
entry_points = []
# Look for common entry point names
entry_names = [
"kgspInitRm_IMPL", "kgspInitRm", "kgspBootGspRm", "kgspBootGspRm_IMPL",
"gspBoot", "gspInit", "gspMain",
"nv_vgpu_vfio_get_ops", "nv_vgpu_vfio_set_ops",
"vgpu_init", "vgpu_init_IMPL",
"vmiop_init", "vmiop_init_IMPL",
"hal_init", "hal_init_IMPL"
]
for name in entry_names:
func = function_manager.getFunction(name)
if func:
entry_points.append({
"name": name,
"entry": str(func.getEntryPoint()),
"size": func.getBody().getNumAddresses()
})
print(f" Found: {name} at {func.getEntryPoint()}")
# Also check for functions called from reset vector / entry
# Look at the first few instructions
entry_addr = program.getMinAddress()
print(f"\nProgram entry address: {entry_addr}")
# 5. Find WPR (Write Protected Region) related code
print("\n--- Finding WPR-related Code ---")
wpr_functions = []
for func in functions:
name_lower = func["name"].lower()
if "wpr" in name_lower or "write_protect" in name_lower or "protect" in name_lower:
wpr_functions.append(func)
print(f"Found {len(wpr_functions)} WPR-related functions")
with open(os.path.join(output_dir, "wpr_functions.json"), "w") as f:
json.dump(wpr_functions, f, indent=2)
# 6. Find memory management functions
print("\n--- Finding Memory Management Functions ---")
mem_keywords = ["alloc", "free", "map", "unmap", "pin", "unpin", "dma", "iommu", "mmio", "bar"]
mem_functions = []
for func in functions:
name_lower = func["name"].lower()
for kw in mem_keywords:
if kw in name_lower:
mem_functions.append(func)
break
print(f"Found {len(mem_functions)} memory management functions")
with open(os.path.join(output_dir, "mem_functions.json"), "w") as f:
json.dump(mem_functions, f, indent=2)
# 7. Find interrupt/MSI-X related functions
print("\n--- Finding Interrupt/MSI-X Functions ---")
irq_keywords = ["irq", "interrupt", "msi", "msix", "eventfd", "doorbell"]
irq_functions = []
for func in functions:
name_lower = func["name"].lower()
for kw in irq_keywords:
if kw in name_lower:
irq_functions.append(func)
break
print(f"Found {len(irq_functions)} interrupt-related functions")
with open(os.path.join(output_dir, "irq_functions.json"), "w") as f:
json.dump(irq_functions, f, indent=2)
# 8. Generate summary report
print("\n--- Generating Summary Report ---")
report = {
"firmware": "gsp-570.144",
"architecture": program.getLanguage().toString(),
"total_functions": len(functions),
"rpc_functions": len(rpc_functions),
"vgpu_strings": len(vgpu_strings),
"entry_points": entry_points,
"wpr_functions": len(wpr_functions),
"mem_functions": len(mem_functions),
"irq_functions": len(irq_functions)
}
with open(os.path.join(output_dir, "analysis_summary.json"), "w") as f:
json.dump(report, f, indent=2)
# Print summary
print(json.dumps(report, indent=2))
# 9. Decompile key functions and save
print("\n--- Decompiling Key Functions ---")
from ghidra.app.decompiler import DecompInterface
from ghidra.util.task import ConsoleTaskMonitor
decompiler = DecompInterface()
decompiler.openProgram(program)
monitor = ConsoleTaskMonitor()
key_functions = entry_points + rpc_functions[:20] + wpr_functions + mem_functions[:10] + irq_functions[:10]
decompiled = {}
for func_info in key_functions:
func = function_manager.getFunctionAt(func_info["entry"])
if func:
result = decompiler.decompileFunction(func, 60, monitor)
if result.decompileCompleted():
decompiled[func_info["name"]] = result.getDecompiledFunction().getC()
print(f" Decompiled: {func_info['name']}")
else:
print(f" Failed to decompile: {func_info['name']}")
# Save decompiled code
with open(os.path.join(output_dir, "decompiled_key_functions.c"), "w") as f:
for name, code in decompiled.items():
f.write(f"\n// ===== {name} =====\n")
f.write(code)
f.write("\n")
print(f"\nDecompiled {len(decompiled)} key functions")
print("Analysis complete!")
|