If the variable is provided, the resulting .dmg will be uploaded to Apple's servers for notarization. If successful, Apple's notarization ticket is attached to the image.
Notarization of ~30MiB .dmg takes 40-50 seconds including upload time, ~30 seconds sans the upload time.
Tested building and notarizing of Rockbox Utility, Rockbox Theme Editor, and both as a single target, i.e. deploy.
Co-authored-by: ChatGPT-5.6 Luna
Change-Id: Ib31b1f825893111d23248fb8511fe5b6c73d5525
A contributor's check archive matches the row exactly and passes
test_crash clean. test_ftl disagrees with the oracle on two logical
pages in one block - a second, distinct false positive from the
A5D5D589 x2 case: a closed data block addressed purely by position,
with one stale leftover page. Confirmed against the decode notes
(_FTLRestore's "closed blocks -> map" step) and documented in
test_ftl.c alongside the existing false positive.
Testing evidence: utils/ipodnano3g/RESULTS.md.
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Change-Id: Ib24d2df18e2b0e60e000ee6ea43bef9c214f7f72
A contributor's check archive matches the row exactly and passes both
host tests clean: test_ftl agrees with the oracle on all 3,964,928
sectors, test_crash survives 100 power cuts with 0 sectors wrong.
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Change-Id: I7c651c94332e0a04686ce8855a274735ae39546c
Four check archives (B614D5EC x2, A5D5D589 x2, A5D5D589 x4, 3E94D589 x2)
all match their table rows and pass test_crash clean. Three pass test_ftl
outright; A5D5D589 x2 disagrees with the oracle on two logical pages,
traced to _FTLRestore's own tie-break between two competing logs
(verified instruction-for-instruction against osos 1.1.3) - Apple's own
firmware would resolve the same medium the same way, so this is not a
defect. test_ftl.c gets a note explaining the false positive for future
archives that hit it.
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Change-Id: If8de0d6b1175981a292c5c45fbc092d5a6e0891a
A contributor's check archive for a 2-chip-enable A5D5D52C unit matches
the row exactly and replays clean against the host FTL suite. The row
moves in with the validated chips on this evidence alone - no on-device
write test has been run.
Testing evidence: utils/ipodnano3g/RESULTS.md.
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Change-Id: Ia9e00c0e880b10785da3ab52bc98dc93e94acfaf
The contributor NAND check tool went in before the driver changes that
followed it. This brings it up to the current tree.
Testing evidence: utils/ipodnano3g/RESULTS.md.
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Change-Id: Ie7712e0d7eaf75b880a9d134715ce1396a8545f8
The host-side tools the Nano 3G NAND driver and FTL were developed and
tested with, so the evidence in those changes can be reproduced and the
next chip can be added without rediscovering any of it: regdiff (register-
write comparison against Apple's sequencer programs), ftltest (the host
FTL test suite), chiptable.py, the FTL decode notes, and RESULTS.md, the
measurements the earlier changes quote.
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Change-Id: I321e06291ca393e18dbd5f71c2c6371fcda9a94d
- The main binary in *.app/Contents/MacOS/ was not signed using the "hardened runtime" option.
- The ipodpatcher and sansapatcher binaries in RockboxUtility.app/Contents/bin/ were not signed at all.
The produced .dmg images are now suitable for notarization so the app inside can be installed and started with no security warnings.
They are not notarized yet, as this takes a significant amount of time, but it can be done manually using:
xcrun notarytool submit build-qt/RockboxUtility.dmg --keychain-profile <your-profile> --wait
xcrun stapler staple build-qt/RockboxUtility.dmg
Only ARM macOS is supported at the moment.
Co-authored-by: ChatGPT-5.6 Luna
Change-Id: Id88d7da18f541f9f503172f5dcb5b17d64e0602e
Rockbox only drives NAND parts proven on hardware, and this tree has one
model to prove them on. This is the image that lets an owner of another
Nano 3G supply what validating theirs takes: a bootloader built with
-DNAND_CHECK and run from DFU, which never touches the NOR flash or
writes to the NAND.
Testing evidence: firmware/target/arm/s5l8702/ipodnano3g/TESTING.md.
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Change-Id: I46328b69f8011337790f35a195de97b5bcf347a5
libusb_control_transfer returns <0 for errors,
0 is success without any bytes, read and ret >0
is the amount if bytes read.
Tested command: sudo ./usbboot --vid 0xa108 --pid 0x1000 --cpuinfo
Before:
Can't get CPU info: 8
After:
CPU info: X1000_v1
Change-Id: Ied6d430406239ea4f99e7c83274d99ae4c555899
Add the HiBy R1 and X1600 USB boot path, sharing the boot-package reader
with X1000. Load the returning USB stage separately from the flash SPL,
check its DDR result, then upload and run the second-stage bootloader.
Built on macOS; error paths checked with mocked USB transfers.
Change-Id: I501c1ffdb9e3d5f0c76a379ec6d229ec579bf100
Apple fitted at least five makers' NAND to the Nano 3G, in eighteen
chip and chip-enable combinations. Rockbox's Nano 3G NAND support can
only be enabled for writing on a chip that has been validated on
hardware, and so far one has. This gives owners of the others a way to
send what validation needs without installing anything.
nano3g-check.dfu runs from DFU mode (mks5lboot --dfusend). It reads the
chip ids on every chip enable, matches Apple's chip table, tries a
read-only mount, and shows a short summary. It then serves the raw NAND
over USB as a write-protected disk: sector 0 a text report, then 16-byte
spare records for every page, then page data. Nothing is written to the
iPod's NAND or NOR.
nandcheck.py collect finds that disk on Linux, macOS or Windows and
writes a few-MB archive: the report, every page's spare metadata and
read result, and every page that is not user data or erased (the FTL
and VFL control structures and Apple's bad-block records). It includes
no file contents and not the serial number. The README lists the chips,
how to tell which one an iPod has, and the procedure.
The image is the Nano 3G bootloader built with -DNAND_CHECK from the
Nano 3G NAND driver work, which is not merged yet.
Tested on a 4GB Nano 3G (Hynix A514D3AD x4): sent with mks5lboot
--dfusend, the disk appears within seconds, and collect reads it in 7
minutes with no ECC failures or timeouts. The archive mounts in the
driver's host FTL tests with every sector resolving to its newest copy.
AI provenance: developed with Claude Opus 5 (Anthropic), used through
Claude Code. The model wrote most of the code and this message under
Andrew Rice's direction. Any hardware testing described above was
carried out by Andrew Rice, who is responsible for this change.
Change-Id: Id790997768ee79451b7adeb5e9764dc8054faf4c
Registers the Nano 3G (platform ipodnano3g, model number 117, "nn3g"
header) so mks5lboot can build DFU installers and uninstallers for it,
adds its original bootloader to the dualboot code, and lists the
platform in the usage text and the README.
The target has to be named ipodnano3g rather than nano3g: the dualboot
Makefile derives the source directory and the piezo driver's file name
from it.
The per-target OF hash table is the substantive change. identify_fw()
decrypts the IM3 header's data_sign with the hardware UKEY and looks it
up in of_sha[], and anything not listed is taken to be a Rockbox
bootloader. The table held only iPod Classic firmware, so on a Nano 3G
the installer took Apple's own bootloader for a Rockbox one and gave up,
and the uninstaller would have refused to restore it. Both bail out
before writing, so nothing is damaged, but neither can work. The table
is now per target, and lists the bootloader of every Nano 3G firmware
release, 1.0.1 to 1.1.3.
The decrypted data_sign is the first 16 bytes of the SHA-1 of the
plaintext bootloader, so it is the same on every unit. Each release's
updater image (aupd, GID-encrypted, in the ipsw) carries that bootloader,
0x1f800 bytes, at the start of a NOR image. The aupd of each release was
decrypted on a Nano 3G with the hardware GID key and hashed on the host.
For 1.1.3 the result matches the data_sign read from a 4GB unit (model
MA978) whose NOR had never been written to, and the bootloader in its
aupd is byte-identical to the decrypted copy the installer relocated on
that unit. 1.1.2 and 1.1.3 ship the same bootloader.
dualboot.c is generated, and only the Nano 3G arrays are added. The iPod
Classic arrays are left byte-for-byte as they were: rebuilding them with
a different compiler changes their bytes, which would ship an untested
installer to Classic users for no reason.
The dualboot Makefile did not build from the current tree for any
target, which the committed blobs, older than both problems, had hidden.
config.h needs autoconf.h, which tools/configure generates per target,
so each target now takes a CONFIGDIR_<target> pointing at a configured
bootloader build for it, e.g.
make CONFIGDIR_ipod6g=../../../build-ipod6g-bl \
CONFIGDIR_ipodnano3g=../../../build-nano3g-bl
And the linker script is preprocessed with __ASSEMBLER__ defined, under
which config.h now emits the ldmpc/ldrpc assembler macros that ld
rejects; the sed that cleans it now also drops .macro, .endm and .syntax
lines and the macro bodies. Before these fixes the iPod Classic build
failed first on the missing autoconf.h and then with a linker syntax
error; with them it builds both blobs.
Tested on that unit, with s5l8702pwnage delivering the images through
Apple's DFU, and again with mks5lboot's own --bl-inst and --bl-uninst:
the installer put Rockbox in NOR, the unit then booted
Rockbox, and holding MENU booted Apple's firmware from the relocated
original bootloader; the uninstaller restored it and the unit booted
Apple's firmware again. Those images carried a table holding only the
1.1.3 entry. The Nano 3G blobs in dualboot.c were then rebuilt with the
Makefile for the full table - with the one-entry table the rebuild was
byte-identical to what the tested images carried - and mks5lboot
--bl-inst with them installed Rockbox on the same unit, which booted
Rockbox and, holding MENU, Apple's firmware. The uninstaller built with
the full table has not been run, and no firmware other than 1.1.3 has
been installed to or uninstalled from on hardware. For the iPod Classic,
the uninstaller DFU this builds is byte-identical to the one built
before this change.
AI provenance: developed with Claude Opus 5 (Anthropic), used through
Claude Code. The model wrote most of the code and this message under
Andrew Rice's direction. Any hardware testing described above was
carried out by Andrew Rice, who is responsible for this change.
Change-Id: I4b2fa692ac4110192ccbde0f1790b0ae2d1c73f5
During Rockbox installation or update, the progress window currently
becomes unresponsive to screen-reader navigation while archive
inspection, free-space calculation and extraction are in progress. A
blind user cannot reliably move through or read the status messages and
therefore cannot determine what the utility is doing, how far the
installation has progressed, or whether an error has occurred.
The cause is that these operations are performed synchronously in the
GUI thread after a package has been downloaded. Although the
installation itself continues, the user interface cannot process
keyboard input and accessibility events reliably until the operation
finishes.
The attached patch moves the package installation work to a low-priority
QThread. Downloading remains asynchronous as before, while progress and
log signals from archive extraction are delivered back to the GUI thread
through Qt connections. This keeps the progress window fully navigable
with a screen reader throughout the installation.
Change-Id: I9a36a736e5b4bf98de8c3a71151679a4c1333dc7
Rockbox Utility currently exposes SAPI5 voice speed but not the SAPI
voice volume. The encoder volume setting is applied after synthesis, so
it cannot prevent clipping or distortion already present in the
generated wave file.
This patch adds a Volume control to the SAPI5 TTS configuration. The
value is passed to the standard SpVoice.Volume property before
synthesis.
Change-Id: Ifa43e55f716f98150e94c86e5e6a6c8bce0ca852
1. The "Ignore files" checkbox was saved in the settings but not
consulted when starting generation. Patterns from the text field were
therefore applied even when the checkbox was unchecked. The pattern list
is now passed to TalkFileCreator only when the option is enabled.
2. Ignore patterns were converted to regular expressions by replacing only
'*' and '?'. Other regular-expression characters were left unescaped and
matches were not properly bounded. The patch uses Qt's
wildcardToRegularExpression() conversion instead.
3. The Talk generation dialog initially focused "Strip Extensions" because of
widget creation order. It now explicitly focuses the folder tree, matching
the task flow and making keyboard and screen-reader use more predictable.
4. The handling of talkclips.ignore is also corrected so that files below a
marked directory are skipped recursively. Previously Rockbox Utility could
generate talkclips.ignore.talk and clips for files below .rockbox even though
.rockbox/talkclips.ignore was present.
Change-Id: I1f9f14ed7fc057bc254f62148a7ef8ffb69425ed
Voice file and Talk clip generation currently run synchronously in the
GUI thread. During long TTS operations this prevents the progress window
from processing input and accessibility events. On Windows this makes
the progress list unavailable to screen readers such as NVDA and can
make Rockbox Utility appear to be hung.
The attached patch moves VoiceFileCreator and TalkFileCreator to
low-priority QThreads while keeping ProgressLoggerGui in the GUI thread.
Progress and log signals are delivered through queued Qt connections.
Cancellation remains available while a synchronous TTS request is
running. The abort flags used across threads are atomic and the abort
signal is sent through a direct connection. Worker objects and threads
are deleted through the standard finished / deleteLater lifecycle.
Talk generation now passes all selected folders to one worker and
processes them sequentially, emitting the final done signal only once.
This preserves multiple-folder selection without starting work in the
GUI thread.
Change-Id: I58aa66333d43e1be249c84e0cf46c17c119a8360
After the SAPI5 error handling added for FS#13972, the Test TTS button
can fail with SAPI error 5 even though the engine and voice are
configured correctly. The test also destroys its QSoundEffect and
temporary file before asynchronous playback can complete.
Config::testTts() used a QTemporaryFile with no .wav extension.
TTSSapi::voice() removes the requested output before synthesis so that a
stale file cannot be mistaken for successful output. SAPI SpFileStream
was therefore asked to create an extensionless output file and returned
error 5 (invalid procedure call or argument).
After successful synthesis, QSoundEffect was allocated on the stack, its
loop count was set to zero, and the temporary file was removed when
testTts() returned. This does not allow asynchronous playback to
complete reliably.
* create a temporary directory and requests an initially
nonexistent tts-test.wav inside it;
* keep the directory and generated wave file alive for playback;
* keep QSoundEffect alive until playback finishes or fails;
* request one playback and clean up all temporary data afterward.
Change-Id: I8e482ab846e6445889118e121025ec48d3776d6b
The existing code treated any ready-read notification from cscript as
proof that synthesis had completed. The SAPI script can emit other
output, so the Utility could check for the wave file before the explicit
SYNC reply and report that the output file did not exist.
The script also used global "On Error Resume Next" without reporting
errors from SpFileStream.Open(), SpVoice.Speak(), or
SpFileStream.Close(). Several waits had no timeout, allowing the GUI
thread to remain blocked indefinitely.
The changes:
* reports SAPI COM errors to Rockbox Utility;
* verifies that SAPI actually created the requested wave file;
* waits for the explicit SYNC reply instead of any process output;
* applies finite timeouts to vendor queries, synthesis, and shutdown;
* terminates a stuck private cscript process safely;
* restarts cscript and retries the current string up to three times when a
third-party SAPI engine stops responding during a long generation run.
Change-Id: I2cf2aefb704353c648bef0c4312f35282ac4e25d
VoiceFileCreator::createVoiceFile() stored corrFile as the address of a
local QTemporaryFile (or a local QFile used as fallback). Both objects
were destroyed before VoiceFileCreator::create() called
TalkGenerator::setLang(), leaving a dangling pointer.
On Windows this produced an access violation in RockboxUtility.exe
immediately after the voice strings had been read. Windows reported
exception 0xc0000005.
The change gives the corrections file QObject lifetime under
VoiceFileCreator, uses the built-in corrections file as a persistent
default, and replaces it with a persistent extracted QTemporaryFile when
extraction succeeds.
Change-Id: I29a371d2431021833676dec2b875186a3c021b13
Without this we'd need 6.7 or newer, which isn't that big of a deal except
we want to support producing RHEL9-based AppImages.
Change-Id: I931be94400d0d19af7fba498f46f174f51a4cd8b
This flag was added in GCC 16; older versions of GCC don't
accept it and don't produce the warning, so they don't need
any special handling.
Change-Id: I13fcba07cafe0b4133de8b03ede681d2454249e4
The warning comes from code generated by QT's MOC, so there isn't
anything to be done until QT addresses this properly.
Change-Id: Ia88ac9af91acbab783b683a6f0b4f4a304aa9e4d
* Ignore 'mock' tts engine
* Must support synthesizing to a file (ie not just "speaking")
* Don't claim 'speak' capabilities if the chosen engine does not
Change-Id: Id5fd224466ed62df5af837256fa66a340672d167
Instead of passing the entire cmdline as a single string that was
treated as the exectuable name on some platforms
Change-Id: Ic4f043a3a48e1b1bfab82bbfa8983c2d224606ec
Implement the available/total functions using QStorageInfo. Unfortunately, QStorageInfo does not provide cluster size, so there's still some platform-specific code left extracted to Utils::filesystemClusterSize().
Co-authored-by: Qwen3.7-Plus
Change-Id: Iacec829b7d12afb65a966fe15e319d305c7384fd
When called with FORMAT_MESSAGE_ALLOCATE_BUFFER you need to pass in
a pointer to an LPSTR, not the LPSTR itself.
Change-Id: Iecc6d79edceb2142d61034d61364262126957b46