The firmware confirms the app slots, and the page numbers them like upstream

UVStudio's own js/flash.js names the protocol: MSG_APP_INFO 0x0730/0x0731, MSG_APP_ERASE 0x0732/0x0733, MSG_APP_WRITE 0x0734/0x0735, MSG_APP_VALIDATE 0x0736/0x0737, with APP_SLOT_COUNT 16, APP_IMG_OFFSET 0x1000, APP_HDR_SIZE 64 and APP_MAGIC 0x31504146 -- the constants this page already used. It uses slots 0..7 and labels them 1..8, and writes the header last so a partial write cannot validate; the page now labels slots the same way.

The Labs build answers 0x0730 over USART, so an installed Beam.app was queried on the radio: slot 0 came back status 0 with the header this page wrote (FAP1, code_size 1100, CRC 0x0d976058, flags 0x0801, name Beam), which confirms the region, the offset and the layout from the firmware's side rather than from a header I read. Slots 1 and 2 answered status 2 with unrelated data -- the overlap the install guard refuses to overwrite.
This commit is contained in:
mckero committed 2026-10-01 17:17:22 +08:00
1 parent 617c1e2dbd
commit 0267371e28
3 files changed
+41 -2

No files matched your search

+20
View File
@@ -589,6 +589,26 @@ Two things measured while wiring it up, both of which changed the code:
differing bytes and read as "the install did nothing" -- the bytes were in the copy. Check
`FlashSlot.path`, not the path you handed in.
Upstream's side of this, read out of UVStudio's own `js/flash.js` rather than guessed:
`MSG_APP_INFO 0x0730/0x0731`, `MSG_APP_ERASE 0x0732/0x0733`, `MSG_APP_WRITE 0x0734/0x0735`,
`MSG_APP_VALIDATE 0x0736/0x0737` -- the same framing as the firmware slots, one family further
along -- and the same constants this page uses (`APP_SLOT_COUNT 16`, `APP_IMG_OFFSET 0x1000`,
`APP_HDR_SIZE 64`, `APP_MAGIC 0x31504146`). Two details from there are worth having: UVStudio
uses only slots 0..7 and **labels them 1..8**, and it writes the header **last**, because the
header carries the committed flag and a partial write must never validate. This page writes a
whole slot at once, which has the same property for free.
The firmware confirmed the whole thing itself. The Labs build answers `0x0730` (app info) over
USART, so an installed `Beam.app` was queried on the radio, not just read back from the file:
0x0730 slot 0 -> status 0
raw 0000 | 46415031 01000101 4c040000 5860970d 0000 0108 | 4265616d 0000
FAP1 hdr1 abi1 api1 1100 CRC 0x0d976058 flags 0x0801 "Beam"
That is the header this page installed, echoed by the running firmware, so the region, the
offset, the layout and the bytes are right. Slots 1 and 2 answered `status 2` with unrelated
data, which is the overlap the install guard exists for.
## The keypad: two real bugs, both fixed
The old note here said "keys reach the firmware but the UI does not react" and
+17
View File
@@ -476,6 +476,23 @@ BroadcastFM)。上游是用 UVStudio 通过 WebSerial 装进去的;在我们
以免正在运行的模拟器脚下的文件被改写。第一版测试断言原文件变了,看到 0 字节差异,读起来像
"安装什么都没做" —— 其实字节在副本里。要检查 `FlashSlot.path`,不是你传进去的路径。
上游那一侧不用猜,直接读 UVStudio 自己的 `js/flash.js`:`MSG_APP_INFO 0x0730/0x0731`、
`MSG_APP_ERASE 0x0732/0x0733`、`MSG_APP_WRITE 0x0734/0x0735`、`MSG_APP_VALIDATE 0x0736/0x0737`
—— 与固件槽位同一套帧格式、再往后一族 —— 以及与本页相同的常量(`APP_SLOT_COUNT 16`、
`APP_IMG_OFFSET 0x1000`、`APP_HDR_SIZE 64`、`APP_MAGIC 0x31504146`)。从那里得到两个细节值得记住:
UVStudio **只用槽 0..7 并显示为 1..8**;而且它**最后才写头** —— 因为头里带着 committed 标志,
写一半绝不能通过校验。本页一次写整个槽,这个性质是白送的。
而整件事最后由**固件自己**确认了。Labs 版会在 USART 上回答 `0x0730`(应用信息),所以装好的
`Beam.app` 是**在电台上被问出来的**,不只是从文件里读回来的:
0x0730 slot 0 -> status 0
raw 0000 | 46415031 01000101 4c040000 5860970d 0000 0108 | 4265616d 0000
FAP1 hdr1 abi1 api1 1100 CRC 0x0d976058 flags 0x0801 "Beam"
这就是本页写进去的那个头,被运行中的固件原样念了回来 —— 所以区域、偏移、布局、字节都是对的。
槽 1 和槽 2 回答 `status 2` 加无关数据,那正是"安装守护"要防的那块重叠区。
## 键盘:两个真 bug,都已修复
这里原来的笔记写的是"按键到达了固件但界面不反应",并且归咎于机器模型。结果发现有**两个
+4 -2
View File
@@ -942,7 +942,7 @@ def render_index(scale: int) -> str:
<label>Overlay apps</label>
<span id="appstate">-</span>
<span class="hint">the Labs edition's apps live in the same external flash (16 slots
from 0x102000, the firmware's menu lists the first eight). Pick a .app for a slot to
from 0x102000; the firmware's menu lists the first eight, numbered 1..8). Pick a .app for a slot to
install it — no serial port and no browser permission are involved</span>
</div>
<table id="apptable"><tbody></tbody></table>
@@ -1300,7 +1300,9 @@ async function loadApps() {{
: s.state === 'empty' ? '<i>Empty</i>'
: '<i>' + s.state + '</i> — not an app';
const size = s.state === 'app' ? s.code_size + ' B' : '';
tr.innerHTML = '<td>app ' + s.slot + (s.slot < 8 ? '' : ' (after the menu)') +
// Upstream and the firmware's own menu number the eight usable slots 1..8, while the
// region has sixteen: slot 0 is "1" there, so show them the same way.
tr.innerHTML = '<td>app ' + (s.slot + 1) + (s.slot < 8 ? '' : ' (after the menu)') +
'</td><td>' + what + '</td><td>' + size + '</td><td></td>';
const td = tr.lastElementChild;
const inp = document.createElement('input');