14 KiB
Simulateur iPod Touch 2G (iPhone OS 2.2.1)
Émulateur qemu-ios (branche iPod Touch 2G, N72AP), adapté pour
démarrer iPhone OS 2.2.1 (5H11a). iPhone OS 2.1.1 (5F138) reste disponible. Les outils sont dans ipod-emu/bin ; dans le workbench actuel, des wrappers les exposent via /home/dev/.local/bin.
Environnement déplacé
Dans le workbench actuel, les projets sont sous /srv/homes/iphoneos2 :
ipod-emu contient les images et les outils, qemu-ios contient QEMU.
Les outils utilisés directement depuis ipod-emu/bin retrouvent ce dossier ;
le lanceur cherche QEMU dans le dossier voisin et transmet son dossier pc-bios
pour retrouver les keymaps VNC après déplacement. IPOD_EMU_HOME, IPOD_QEMU,
IPOD_QEMU_DATA et IPOD_QMP permettent de choisir d'autres chemins.
ipod-qmp respecte également IPOD_EMU_HOME pour le socket de session.
Vérifier les liens symboliques des images après déplacement : le lien de
images/5H11a/bootrom doit viser ../5F138/bootrom, plutôt qu'un ancien home absolu.
Sur Arch, le binaire construit dans cet environnement utilise notamment pixman,
libpng, libjpeg-turbo, sdl2 et libslirp ; les captures PNG utilisent
imagemagick. Compiler le relais réseau demande aussi pkgconf et glib2-devel.
Ces dépendances doivent être présentes dans chaque nouveau conteneur.
Le lanceur échoue explicitement si QEMU ou le relais réseau s'arrête au démarrage.
Un port agent déjà occupé est une erreur : le relais ne poursuit plus sans sa
redirection. stop nettoie le relais suivi par PID même si QEMU est déjà arrêté.
Utilisation
ipod-emu start -w 5H11a-agent-v12 -W # attend SpringBoard et déverrouille (~25–50 s)
# Ajouter -f uniquement pour remettre la NAND à zéro.
ipod-qmp screenshot ecran.png # capture 320x480
ipod-qmp tap 160 326 # touche (coordonnées écran), ipod-qmp tap X Y 1.5 = appui long
ipod-qmp swipe 300 250 20 250 # glisser (ex. page suivante de SpringBoard)
ipod-qmp home | power # boutons
ipod-emu log # console du kernel + syslog iOS
ipod-emu stop
- Attendre
ipod-emu wait/start -Wavant les gestes : le pilote tactile invité doit avoir terminé son démarrage. - VNC sur
127.0.0.1:5900pour interagir à la main (tunnel SSH :ssh -L 5900:127.0.0.1:5900 …). - Le lancement d'une app prend 10-20 s.
Déverrouillage après redémarrage
Avec l'agent v11 ou ultérieur, start -W et wait vérifient le verrouillage, réveillent
l'écran et effectuent le glissement normal avant de rendre la main.
ipod-agent screen retourne locked=0 passcode=0 une fois déverrouillé ;
ipod-agent unlock permet de refaire ce parcours après démarrage.
Si un code est activé, le client s'arrête et demande un déverrouillage manuel.
Aucun geste n'est envoyé avant les marqueurs de démarrage du pilote tactile.
Le réveil utilise SBDimScreen(port, false), puis un glissement de (60,450)
à (319,450) adapté à la surface tactile du modèle. Le client laisse deux
secondes au réveil et à la fin du geste, puis vérifie le verrouillage ; trois
essais maximum. SBApplicationRequestedDeviceUnlock affiche le clavier de code
sur 2.2.1 même sans code actif : ce n'est pas le parcours utilisé.
Une image contenant l'agent v10 doit être mise à jour avant d'utiliser ce workflow. Créer une image distincte préserve l'image de base :
cd /srv/homes/iphoneos2/ipod-emu/agent
PATH=/opt/cctools/bin:$PATH make
ipod-mkimage -o 5H11a-agent-v11 overlay
Le firmware se choisit avec start -w 5H11a-agent-v11 -W. Attention : comme pour
tout changement de firmware, cette commande remplace la NAND du dossier run ;
conserver sa session précédente ou utiliser un environnement de test séparé.
Le dossier de diagnostic work/reprise-20260930 conserve une session avec l'agent
v11 et HelloEmu, indépendante de la session d'origine.
Tester nos apps
ipod-mkimage -b 5H11a-agent-v11 MonApp.app autre.ipa paquet.deb # -> images/5H11a-agent-v11-apps
ipod-emu start -f -W -w 5H11a-agent-v11-apps
ipod-agent launch com.exemple.monapp --log /private/var/mobile/monapp.log
ipod-agent get /private/var/mobile/monapp.log
# Installation sans reconstruire l'image (synchronise puis redémarre l'iPod) :
ipod-agent push-app MonApp.app
Les .app/.ipa vont dans /Applications (re-signés avec ldid -S ; le kernel les accepte grâce au boot-arg
amfi_allow_any_signature injecté par l'émulateur), les .deb sont décompressés à la racine. Compiler en armv6 avec
la toolchain de l'environnement (arm-apple-darwin9-gcc -isysroot /opt/theos/sdks/iPhoneOS2.2.1.sdk), voir
apps/HelloEmu. Environ 230 Mo libres dans l'image 2.2.1.
Test automatique et diagnostics
# Construire d'abord l'agent v12 et une image dédiée depuis la base inchangée :
PATH=/opt/cctools/bin:$PATH make -C agent
ipod-mkimage -b 5H11a -o 5H11a-agent-v12 agent/overlay
# Après avoir arrêté sa session, tester dans une NAND indépendante :
ipod-test-app MonApp.app
ipod-test-app MonApp.ipa --output /chemin/nouveau-dossier
ipod-test-app paquet.deb --bundle-id com.exemple.monapp
Les chemins agent/ ci-dessus sont relatifs au dossier des outils ; dans le dépôt,
utiliser contrib/ipod-emu/agent. Choisir un nom d'image absent lors de sa création.
--base permet de choisir une autre image contenant l'agent v11 ou ultérieur.
Le bundle-id est lu dans le plist des .app et .ipa ; il doit être fourni pour
les .deb et overlays. Le runner refuse de démarrer si les ports VNC ou agent
sont déjà occupés. Chaque test crée une image et une session dans son propre
répertoire ; la NAND de run/ et l'image de base restent conservées.
Le code de sortie vaut zéro uniquement si l'app apparaît puis reste au premier
plan pendant --settle secondes (3 par défaut), si les diagnostics sont collectés
et si la VM est arrêtée. Ce contrôle ne remplace pas les tests fonctionnels de l'app.
Les résultats vont dans work/tests/<date>-<identifiant>/, ou dans un nouveau dossier
--output : result.json, workflow.log, app.log, screen.png et les logs QEMU,
série et réseau dans session/run/. En cas d'échec, les diagnostics disponibles
sont conservés et la session de test est arrêtée.
Tactile et transferts
Home/Power ne doivent plus écrire hors du tableau GPIO : le port C est inclus. Les trous des registres SYSIC ne débordent plus dans le groupe voisin. Le tactile traite séparément les requêtes de longueur et de données, accepte EA/EB, conserve une trame stable, et abandonne proprement une commande lors de la réinitialisation SPI. Les commandes et rapports inconnus ne font plus arrêter QEMU. Le découpage des requêtes est documenté également dans OpeniBoot Z2.
La vitesse verticale utilise y, les vitesses conservent leur signe et sont
bornées à 16 bits. apps/TouchProbe permet de mesurer la calibration : compiler
avec son Makefile, lancer avec --log, puis comparer les gestes QMP au marqueur
bleu et aux coordonnées du journal (ajouter 20 pixels à l'ordonnée locale de la vue).
La calibration a été vérifiée sur 5H11a et 5F138, sur sept points de (20,40) à (300,460).
Agent v12 : put et get utilisent des blocs de 64 Kio au lieu d'allouer
le fichier entier dans l'iPod. Un upload incomplet supprime son temporaire et
conserve le fichier précédent ; le client fait de même pour les téléchargements.
Le protocole reste compatible avec l'agent v11. Les téléchargements vers stdout
peuvent naturellement afficher un préfixe avant une erreur de transport.
Depuis le dépôt, les tests sans firmware sont :
contrib/ipod-emu/tests/run-rtc # protocole I²C et horloge D1759, ASan/UBSan
contrib/ipod-emu/tests/run-multitouch # build QEMU arm existant, Ninja, compilateur avec ASan/UBSan
python3 contrib/ipod-emu/tests/test-transfers.py # Python et compilateur C, sockets locales
Validation sous iPhone OS 2.1.1
Le firmware 5F138 a été vérifié avec l'agent v12 et les mêmes corrections QEMU. Conserver l'image 5F138 d'origine et produire une image dérivée avec un nom absent :
ipod-mkimage -b 5F138 -o 5F138-agent-v12 agent/overlay apps/TouchProbe/TouchProbe.app apps/HelloEmu/HelloEmu.app
Utiliser ensuite un environnement IPOD_EMU_HOME indépendant pour démarrer cette
image ; un changement de firmware remplace la NAND de la session choisie.
SystemVersion.plist confirme iPhone OS 2.1.1 / 5F138. Les sept points de
calibration sont exacts et six cycles de veille/réveil alternant Home et Power
passent, sans désactivation du tactile.
Pour tester Safari sans dépendre d'un site extérieur, depuis le dépôt :
python3 contrib/ipod-emu/tests/http-fixture.py --output /chemin/diagnostic-http
Ouvrir l'URL http://10.0.2.2:<port>/ affichée dans Safari invité. Le serveur
écoute uniquement sur la boucle locale de l'hôte ; il conserve le port et les
requêtes dans le dossier choisi. Saisir bonjour avec le clavier virtuel et
soumettre : le journal doit contenir /submit?texte=bonjour. Suivre le lien de
défilement, glisser jusqu'au bas, attendre la fin de l'inertie et toucher le lien
final : /fin doit apparaître. Arrêter le serveur avec Ctrl-C après le test.
Attendre l'affichage réel d'une application avant d'envoyer des gestes. Pour
TouchProbe, attendre TouchProbe ready dans le journal ; une réponse de lancement
ne garantit pas que la vue soit déjà prête. Sous 2.1.1, lancer Safari avec --url
alors qu'il est déjà ouvert n'a pas changé la page lors du test ; utiliser les
liens de la page ou relancer Safari pour ouvrir une autre URL.
Notes et la calculatrice complètent ce contrôle : saisir une note, la sauvegarder,
puis comparer son texte dans Library/Notes/notes.db avant et après redémarrage ;
vérifier visuellement 7 × 8 = 56 dans la calculatrice. Les diagnostics et le
résultat détaillé de la validation du 1er octobre sont décrits dans HANDOFF.md.
Limites
- Persistance NAND : les pages et métadonnées écrites par iOS, ainsi que les effacements de blocs, sont conservés
dans
run/nand.ipod-emu startconserve cet état ;-fou un changement de firmware le remplace par l'image de base. Les images produites pargen-v1/mknandutilisent le format VSVFL de production etnand-write=on. Les anciennes images demknand-v1doivent être reconstruites avant d'activer les écritures. - Internet : PPP sur UART1, pont
ipod-netdvers libslirp ; DNS et HTTP fonctionnent.ipod-agent fetch http://example.com/teste le réseau depuis l'iPod. L'écran Réglages affiche toujours « Pas de Wi-Fi », car la puce BCM4325 n'est pas émulée. - Heure : le RTC D1759 fournit l'heure dès le démarrage, avec la configuration QEMU
-rtc(UTC et horloge hôte par défaut).start -W/waitne modifie plus la date.ipod-agent settime SECONDES_UNIXreste disponible pour les tests explicites. Le décalage écrit par iOS reste en mémoire pendant la session ; une nouvelle instance QEMU repart de sa base RTC. Les IRQ d'alarme matérielle ne sont pas émulées. Voir RTC.md. L'image de base est en français, région France, fuseau Europe/Paris. - Relance de SpringBoard :
respringpeut bloquer la reconstruction du catalogue d'apps.push-appredémarre donc l'émulateur sans reconstruire l'image ni réinitialiser la NAND. Avec l'agent v11, le déverrouillage puis le lancement de HelloEmu au premier plan sont validés après cette installation. Les corrections GPIO/SPI ont permis huit cycles veille/réveil alternant Home et Power sur 5H11a. Le déverrouillage automatique continue à vérifier l'état de l'écran. - Veille : l'agent v10 pose
SleepDisabledsurIOPMrootDomain, le SoC ne sachant pas reprendre une veille profonde. - Pas de son, pas d'accélération graphique (SpringBoard tourne avec
LK_ENABLE_MBX2D=0).
Reconstruire les images
ipod-build-fw 5H11a télécharge l'IPSW iPod2,1 chez Apple et les clés sur api.ipsw.me, génère la NOR, déchiffre et
adapte le rootfs (bin/mkbase-rootfs : LaunchDaemons réduits, fstab à une partition, activation Lockdown
d'assets/Lockdown, verrouillage auto désactivé) et génère la NAND (gen-v1/mknand, format VSVFL de production du générateur
qemu-ios-generate-nand 2ee0d46, signature de format 2 et écritures activées). L'image 5F138 vient de la release n72ap_v1 de qemu-ios.
Ce qui a été modifié dans qemu-ios (~/qemu-ios)
ipod_touch_aes.c: clés GID choisies d'après le contenu du KBAG (tableipod_touch_gid_keys.h, 5F138 + 5H11a) au lieu de l'ordre des appels ; le dernier bloc incomplet d'une image IMG3 est laissé en clair (supprime les hacks Adler32 du kernel et de fin de DeviceTree) ; patch de la vérif de longueur LZSS d'iBoot trouvé par signature.ipod_touch_sha1.c: réécrit comme la fonction de compression SHA1 du matériel (état lisible/écrivable,0x2= premier bloc,0xa= suite) + interruption de fin (IRQ 40, registre0x0c) — utilisés par le kernel 2.2.1 pour la signature des pages de code etIOSHA1Accelerator.ipod_touch_fmss.c: chemin Bluetooth dans iBoot trouvé par recherche ; décodage des listes de programmation, persistance des données et des 12 octets de métadonnées, effacement des blocs de 128 pages ; indicateur de page vierge dans0xC30, nécessaire à la récupération FTL après arrêt de QEMU.ipod_touch_mipi_dsi.c: le bit d'horloge prête suitCLKCTRL[31], permettant au pilote de terminer l'arrêt de l'écran. Le SoC ne sait pas encore sortir de veille ; garder le verrouillage automatique désactivé.ipod_touch_uart.c: UART avec FIFO et interruptions utilisées par PPP.ipod_touch_mbx.c: patch BCM4325 du kernel limité à 5F138.ipod_touch_2g.c: stubs mémoire MPVD (0x39600000, kernel panic à la mise en veille) et0x38100000(écrit par LLB 2.2.1), option machinelegacy-nor(NOR à tags SHSH non chiffrés,offpour les NOR générées ici).- xpwn
hfs/hfslib.c: aprèsgrow, les nouveaux fichiers sont alloués dans l'espace ajouté (sinon fragmentés).