Skip to content

Commit d824e44

Browse files
committed
!cleanup!
1 parent 48a05c1 commit d824e44

File tree

11 files changed

+274
-148
lines changed

11 files changed

+274
-148
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
Volume Zero, Issue 3, Phile 1 of 1
33
44
M5PORKCHOP README
5-
v0.1.8b-heapkampf
5+
v0.1.8b-PSTH
66
77
^__^
88
(oo)\_______

platformio.ini

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
platform = espressif32@6.12.0
55
board = m5stack-stamps3
66
framework = arduino
7-
custom_version = 0.1.8b-heapkampf
7+
custom_version = 0.1.8b-PSTH
88
board_build.mcu = esp32s3
99
board_build.f_cpu = 240000000L
1010
board_build.flash_mode = qio

scripts/build_release.py

Lines changed: 110 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,17 @@
66
77
--[ 0x00 - What This Does
88
9-
Builds both release binaries for distribution:
10-
9+
Builds release binaries for distribution:
10+
1111
1. firmware_vX.X.X.bin - Flash at 0x10000 via esptool-js
1212
(preserves XP, for upgrades)
13-
13+
1414
2. porkchop_vX.X.X_m5burner.bin - Flash at 0x0 via M5 Burner
1515
(full image, nukes NVS)
1616
17+
3. porkchop_vX.X.X_m5burner.zip - M5Burner catalog package
18+
(m5burner.json + address-named bins)
19+
1720
Output lands in m5porkchop_builds/ directory.
1821
1922
@@ -39,11 +42,13 @@
3942
import subprocess
4043
import shutil
4144
import re
45+
import json
46+
import zipfile
4247
from pathlib import Path
4348

4449
# Phrack-style banner
4550
BANNER = r"""
46-
██▓███ ▒█████ ██▀███ ██ ▄█▀ ▄████▄ ██░ ██ ▒█████ ██▓███
51+
██▓███ ▒█████ ██▀███ ██ ▄█▀ ▄████▄ ██░ ██ ▒█████ ██▓███
4752
▓██░ ██▒▒██▒ ██▒▓██ ▒ ██▒ ██▄█▒ ▒██▀ ▀█ ▓██░ ██▒▒██▒ ██▒▓██░ ██▒
4853
▓██░ ██▓▒▒██░ ██▒▓██ ░▄█ ▒▓███▄░ ▒▓█ ▄ ▒██▀▀██░▒██░ ██▒▓██░ ██▓▒
4954
▒██▄█▓▒ ▒▒██ ██░▒██▀▀█▄ ▓██ █▄ ▒▓▓▄ ▄██▒░▓█ ░██ ▒██ ██░▒██▄█▓▒ ▒
@@ -73,109 +78,169 @@ def log_info(msg):
7378
def get_version():
7479
"""Extract version from platformio.ini"""
7580
ini_path = Path(__file__).parent.parent / "platformio.ini"
76-
81+
7782
if not ini_path.exists():
7883
log_err("platformio.ini not found - are you in the right directory?")
7984
sys.exit(1)
80-
85+
8186
with open(ini_path, "r") as f:
8287
content = f.read()
83-
84-
# Look for custom_version = X.X.X or X.X.X_suffix
85-
match = re.search(r'custom_version\s*=\s*([\d.]+[\w_]*)', content)
88+
89+
# Match version strings like 0.1.8b-PSTH, 0.1.8b_suffix, 0.1.8b
90+
match = re.search(r'custom_version\s*=\s*([\w.\-]+)', content)
8691
if match:
8792
return match.group(1)
88-
93+
8994
log_err("Could not find custom_version in platformio.ini")
9095
sys.exit(1)
9196

9297

9398
def run_cmd(cmd, description):
9499
"""Run a command and handle errors"""
95100
log_info(f"{description}...")
96-
101+
97102
try:
98103
result = subprocess.run(
99104
cmd,
100105
shell=True,
101106
capture_output=True,
102107
text=True
103108
)
104-
109+
105110
if result.returncode != 0:
106111
log_err(f"Command failed: {cmd}")
107112
log_err(result.stderr)
108113
sys.exit(1)
109-
114+
110115
return result.stdout
111116
except Exception as e:
112117
log_err(f"Exception running command: {e}")
113118
sys.exit(1)
114119

115120

121+
def create_m5burner_package(builds_dir, version, bootloader_src, partitions_src, firmware_src):
122+
"""Create M5Burner-compatible ZIP package with manifest and address-named bins"""
123+
log_info("Creating M5Burner catalog package...")
124+
125+
pkg_dir = builds_dir / f"porkchop_v{version}_m5burner_pkg"
126+
fw_dir = pkg_dir / "firmware"
127+
128+
# Clean previous package
129+
if pkg_dir.exists():
130+
shutil.rmtree(pkg_dir)
131+
fw_dir.mkdir(parents=True)
132+
133+
# Copy bins with M5Burner address-naming convention
134+
shutil.copy2(bootloader_src, fw_dir / "bootloader_0x0.bin")
135+
shutil.copy2(partitions_src, fw_dir / "partitions_0x8000.bin")
136+
shutil.copy2(firmware_src, fw_dir / "porkchop_0x10000.bin")
137+
138+
# Generate m5burner.json manifest
139+
manifest = {
140+
"name": "PORKCHOP",
141+
"version": version,
142+
"description": "WiFi pentesting & wardriving tool for M5Stack Cardputer",
143+
"keywords": "wifi,wardriving,pentesting,handshake,spectrum,deauth",
144+
"author": "0ct0",
145+
"repository": "https://github.com/0ct0-porkchop/porkchop",
146+
"framework": "arduino",
147+
"firmware_category": {
148+
"PORKCHOP": {
149+
"path": "firmware",
150+
"device": ["M5Cardputer"],
151+
"default_baud": 921600
152+
}
153+
}
154+
}
155+
156+
manifest_path = pkg_dir / "m5burner.json"
157+
with open(manifest_path, "w") as f:
158+
json.dump(manifest, f, indent=2)
159+
160+
# Create ZIP
161+
zip_path = builds_dir / f"porkchop_v{version}_m5burner.zip"
162+
with zipfile.ZipFile(zip_path, "w", zipfile.ZIP_DEFLATED) as zf:
163+
for file in pkg_dir.rglob("*"):
164+
if file.is_file():
165+
arcname = file.relative_to(pkg_dir)
166+
zf.write(file, arcname)
167+
168+
# Cleanup staging directory
169+
shutil.rmtree(pkg_dir)
170+
171+
size_kb = zip_path.stat().st_size / 1024
172+
log_ok(f"Created: {zip_path.name} ({size_kb:.1f} KB)")
173+
174+
return zip_path
175+
176+
116177
def main():
117178
print(BANNER)
118-
179+
119180
# Get project root (parent of scripts/)
120181
project_root = Path(__file__).parent.parent
121182
os.chdir(project_root)
122-
183+
123184
log_info(f"Working directory: {project_root}")
124-
185+
125186
# Get version
126187
version = get_version()
127188
log_ok(f"Building version: {version}")
128-
189+
129190
# Create output directory
130191
builds_dir = project_root / "m5porkchop_builds"
131192
builds_dir.mkdir(exist_ok=True)
132193
log_ok(f"Output directory: {builds_dir}")
133-
194+
134195
# Build paths
135196
build_dir = project_root / ".pio" / "build" / "m5cardputer"
136197
firmware_src = build_dir / "firmware.bin"
137198
bootloader_src = build_dir / "bootloader.bin"
138199
partitions_src = build_dir / "partitions.bin"
139-
200+
140201
# Output filenames
141202
firmware_dst = builds_dir / f"firmware_v{version}.bin"
142203
m5burner_dst = builds_dir / f"porkchop_v{version}_m5burner.bin"
143-
204+
144205
# Step 1: Build with PlatformIO
145206
log("")
146207
log("=" * 60)
147208
log("STEP 1: Building firmware with PlatformIO")
148209
log("=" * 60)
149-
210+
150211
run_cmd("pio run -t clean -e m5cardputer", "Cleaning build artifacts")
151212
run_cmd("pio run -e m5cardputer", "Compiling")
152213
log_ok("Firmware compiled successfully")
153-
214+
154215
# Verify build artifacts exist
155216
if not firmware_src.exists():
156217
log_err(f"firmware.bin not found at {firmware_src}")
157218
sys.exit(1)
158-
219+
159220
if not bootloader_src.exists():
160221
log_err(f"bootloader.bin not found at {bootloader_src}")
161222
sys.exit(1)
162-
223+
224+
if not partitions_src.exists():
225+
log_err(f"partitions.bin not found at {partitions_src}")
226+
sys.exit(1)
227+
163228
# Step 2: Copy firmware.bin for esptool-js upgrades
164229
log("")
165230
log("=" * 60)
166231
log("STEP 2: Copying firmware for esptool-js upgrades")
167232
log("=" * 60)
168-
233+
169234
shutil.copy2(firmware_src, firmware_dst)
170235
size_kb = firmware_dst.stat().st_size / 1024
171236
log_ok(f"Created: {firmware_dst.name} ({size_kb:.1f} KB)")
172-
173-
# Step 3: Create merged binary for M5 Burner
237+
238+
# Step 3: Create merged binary for M5 Burner (direct flash)
174239
log("")
175240
log("=" * 60)
176241
log("STEP 3: Creating merged binary for M5 Burner")
177242
log("=" * 60)
178-
243+
179244
# Build the esptool merge command
180245
merge_cmd = (
181246
f'pio pkg exec -p tool-esptoolpy -- esptool.py '
@@ -186,12 +251,22 @@ def main():
186251
f'0x8000 "{partitions_src}" '
187252
f'0x10000 "{firmware_src}"'
188253
)
189-
254+
190255
run_cmd(merge_cmd, "Merging binaries")
191-
256+
192257
size_kb = m5burner_dst.stat().st_size / 1024
193258
log_ok(f"Created: {m5burner_dst.name} ({size_kb:.1f} KB)")
194-
259+
260+
# Step 4: Create M5Burner catalog package (ZIP with manifest)
261+
log("")
262+
log("=" * 60)
263+
log("STEP 4: Creating M5Burner catalog package")
264+
log("=" * 60)
265+
266+
zip_path = create_m5burner_package(
267+
builds_dir, version, bootloader_src, partitions_src, firmware_src
268+
)
269+
195270
# Summary
196271
log("")
197272
log("=" * 60)
@@ -206,9 +281,12 @@ def main():
206281
log(f" {m5burner_dst.name}")
207282
log(f" -> Flash at 0x0 via M5 Burner (full install)")
208283
log("")
284+
log(f" {zip_path.name}")
285+
log(f" -> M5Burner catalog package (m5burner.json + bins)")
286+
log("")
209287
log_info(f"Files are in: {builds_dir}")
210288
log("")
211-
289+
212290
return 0
213291

214292

src/build_info.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// Auto-generated build info
22
#pragma once
3-
#define BUILD_TIME "2026-02-08T01:44:20.292145"
4-
#define BUILD_VERSION "0.1.8b-heapkampf"
5-
#define BUILD_COMMIT "e4fd745"
3+
#define BUILD_TIME "2026-02-08T03:36:59.286318"
4+
#define BUILD_VERSION "0.1.8b-PSTH"
5+
#define BUILD_COMMIT "48a05c1"

src/core/heap_health.cpp

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ static uint32_t pendingToastMs = 0;
2929
// Graduated pressure level with hysteresis
3030
static HeapPressureLevel pressureLevel = HeapPressureLevel::Normal;
3131
static uint32_t lastPressureChangeMs = 0;
32+
static uint8_t escalationCount = 0;
3233

3334
// Knuth's Rule metric: free_blocks / allocated_blocks
3435
static float knuthRatio = 0.0f;
@@ -132,17 +133,23 @@ void update() {
132133
// --- Graduated pressure level with hysteresis ---
133134
HeapPressureLevel newLevel = computePressureLevel(freeHeap, fragRatio);
134135
if (newLevel != pressureLevel) {
135-
// Allow immediate escalation (getting worse), but require
136-
// hysteresis delay before de-escalation (getting better)
137136
if (newLevel > pressureLevel) {
138-
// Escalating: apply immediately
139-
pressureLevel = newLevel;
140-
lastPressureChangeMs = now;
137+
// Escalating: require 2 consecutive samples (except Critical = immediate)
138+
escalationCount++;
139+
uint8_t threshold = (newLevel == HeapPressureLevel::Critical) ? 1 : 2;
140+
if (escalationCount >= threshold) {
141+
pressureLevel = newLevel;
142+
lastPressureChangeMs = now;
143+
escalationCount = 0;
144+
}
141145
} else if ((now - lastPressureChangeMs) >= HeapPolicy::kPressureHysteresisMs) {
142146
// De-escalating: only after hysteresis period
143147
pressureLevel = newLevel;
144148
lastPressureChangeMs = now;
149+
escalationCount = 0;
145150
}
151+
} else {
152+
escalationCount = 0;
146153
}
147154

148155
// --- Adaptive conditioning trigger ---

0 commit comments

Comments
 (0)