Fiabiliser le simulateur et déverrouiller SpringBoard après installation #1

Merged
Mahtan merged 3 commits from agent/reprise-simulateur into ipod_touch_2g 2026-09-30 17:13:14 +02:00
7 changed files with 257 additions and 20 deletions

No files matched your search

+56
View File
@@ -146,3 +146,59 @@ Debug : `IPOD_QEMU_EXTRA="-d unimp,guest_errors -D ~/ipod-emu/run/int.log"` ; `I
- `-f` efface la session persistée. Ne pas l'utiliser pour vérifier la conservation d'un fichier.
- QEMU et netd sont lancés avec `setsid` pour survivre à la fin du terminal appelant. Le launcher suit netd par PID.
- Un `.deb` 2.x qui dépend d'un jailbreak (bash, etc.) ne marchera pas : aucun shell dans l'image.
## Reprise du 30 septembre 2026 — après déplacement des homes
- Projets retrouvés sous `/srv/homes/iphoneos2/{ipod-emu,qemu-ios}`.
- Bibliothèques QEMU/libslirp et ImageMagick réinstallées dans le conteneur courant ;
lien BootROM 5H11a corrigé en relatif ; commandes accessibles par wrappers dans
`/home/dev/.local/bin`. Ces installations locales ne modifient pas l'image Docker.
- Lanceur adapté aux chemins déplacés, sélection automatique des keymaps via `-L`,
contrôle du démarrage QEMU et du relais, nettoyage du relais même après arrêt QEMU.
`ipod-qmp` prend en compte `IPOD_EMU_HOME`.
- Test sur une copie de NAND dans `ipod-emu/work/reprise-20260930` : boot de l'image
de base en 28 s, Safari et HTTP validés. `push-app HelloEmu.app` copie les deux
fichiers, redémarre sans réinitialiser la NAND ; HelloEmu apparaît ensuite dans
le catalogue `apps`. Le lancement répond toujours `device locked`, écran noir.
Le programme de diagnostic `unlock` retourne 0 sans débloquer le lancement.
Ne pas considérer le lancement après installation comme validé.
- La copie de la session initiale est conservée dans
`work/reprise-20260930/run-session-initiale` ; la session d'origine `run/nand`
n'a pas été modifiée. Les captures et préférences de diagnostic sont dans le
dossier de reprise. Les sessions de test ont été arrêtées.
- Un ancien relais survivant à QEMU occupait 7788 : supprimé avant de refaire le
test. L'ancien code continuait malgré l'échec de redirection ; le nouveau échoue.
- Vérifications : syntaxe Bash/Python, compilation du relais avec `-Wall`,
échec QEMU volontaire détecté immédiatement, port 7788 occupé détecté et QEMU
arrêté, `stop` après échec. Aucun changement des modèles matériels dans cette reprise.
## Correction du verrouillage — agent v11
- `SBGetScreenLockStatus` confirme `locked=1 passcode=0` après redémarrage.
`SBApplicationRequestedDeviceUnlock` réveille un clavier de code sans déverrouiller.
- Solution validée : `SBDimScreen(port, false)`, attendre deux secondes, glisser
`(60,450)` → `(319,450)`, attendre deux secondes, vérifier `locked=0`.
Le geste historique `(40,430)` → `(280,430)` n'atteint pas correctement le bord
de la surface tactile émulée. Home/Power et gestes lors de la reprise du pilote
peuvent encore provoquer un arrêt QEMU ; aucun correctif matériel n'est revendiqué.
- Agent v11 : commandes `screen` et `wake`. Client : `unlock`, vérification des
marqueurs de disponibilité, refus si un code est actif, trois essais maximum.
`start -W` / `wait` ne rendent la main avec succès qu'après déverrouillage.
- Validations sans débogueur sur la session copiée : démarrage en 36 s ; nouvelle
installation de HelloEmu avec `push-app`, redémarrage conservant la NAND en 47 s,
`launch` réussi et `front` = `com.allovoisins.helloemu`. Capture :
`work/reprise-20260930/hello-v11-apres-push.png`.
- L'agent v11 a été installé atomiquement dans la session de test puis synchronisé
avant redémarrage ; aucune relance à chaud de l'agent/PPP.
Nouvelle image `images/5H11a-agent-v11` construite avec l'overlay de l'agent,
sans modifier l'image 5H11a ni la NAND d'origine. L'image de base v10 doit être
mise à jour avant d'utiliser le déverrouillage automatique.
- La faute `diff_y` utilisant `x` dans `get_frame` reste à étudier séparément ;
elle n'a pas été modifiée pour cette validation.
## Relecture avant merge
- Corrigé `start -W` sur une session déjà lancée : attendre et vérifier le
déverrouillage avant de rendre la main, au lieu de retourner immédiatement.
- Image distincte 5H11a-agent-v11 démarrée et déverrouillée en 27 s ; agent v11
confirmé. Les deux sessions de test antérieures sont conservées séparément.
+59 -6
View File
@@ -1,12 +1,33 @@
# Simulateur iPod Touch 2G (iPhone OS 2.2.1)
Émulateur [qemu-ios](https://git.mahtan-melwasul.com/Mahtan/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 `/opt/ios-legacy/bin`.
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
```bash
ipod-emu start -W # démarre 2.2.1 en conservant la NAND et attend SpringBoard (~25–50 s)
ipod-emu start -W # agent v11 : conserve la NAND, attend SpringBoard et déverrouille (~35–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
@@ -21,11 +42,41 @@ ipod-emu stop
- VNC sur `127.0.0.1:5900` pour 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**, `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 :
```bash
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
```bash
ipod-mkimage MonApp.app autre.ipa paquet.deb # -> images/5H11a-apps (base : -b 5H11a ou -b 5F138)
ipod-emu start -f -W -w 5H11a-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
@@ -51,8 +102,10 @@ la toolchain de l'environnement (`arm-apple-darwin9-gcc -isysroot /opt/theos/sdk
avant la fin du démarrage de SpringBoard.
L'image de base est en français, région France, fuseau Europe/Paris.
- **Relance de SpringBoard** : `respring` peut bloquer la reconstruction du catalogue d'apps. `push-app` redémarre
donc l'émulateur. Après un redémarrage d'une session conservée, le verrouillage iOS peut encore empêcher un
lancement (`device locked`) ; le lancement d'une app installée ainsi n'est pas encore validé.
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 gestes Home/Power restent
susceptibles de déclencher un défaut du pilote lors de la reprise de l'écran ; le workflow automatique utilise
le réveil par l'API d'affichage et vérifie le verrouillage.
- **Veille** : l'agent v10 pose `SleepDisabled` sur `IOPMrootDomain`, 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`).
+30 -2
View File
@@ -67,7 +67,7 @@ struct rt_msghdr {
#include <notify.h>
#include <unistd.h>
#define VERSION "10"
#define VERSION "11"
#define PORT 7788
#define PPP_TTY "/dev/tty.bluetooth"
#define GUEST_IP "10.0.2.15"
@@ -332,6 +332,9 @@ static void cmd_exec(int fd, char **args, int nargs)
static int (*p_SBSLaunchApplication)(CFStringRef, CFURLRef, CFArrayRef, CFDictionaryRef, CFStringRef, CFStringRef, unsigned);
static CFStringRef (*p_SBSApplicationLaunchingErrorString)(int);
static CFStringRef (*p_SBSCopyFrontmostApplicationDisplayIdentifier)(void);
static unsigned (*p_SBSSpringBoardServerPort)(void);
static int (*p_SBGetScreenLockStatus)(unsigned, unsigned char *, unsigned char *);
static int (*p_SBDimScreen)(unsigned, unsigned char);
static void load_sbs(void)
{
@@ -339,6 +342,9 @@ static void load_sbs(void)
if (h) return;
h = dlopen("/System/Library/PrivateFrameworks/SpringBoardServices.framework/SpringBoardServices", RTLD_NOW);
if (!h) return;
p_SBSSpringBoardServerPort = dlsym(h, "SBSSpringBoardServerPort");
p_SBGetScreenLockStatus = dlsym(h, "SBGetScreenLockStatus");
p_SBDimScreen = dlsym(h, "SBDimScreen");
p_SBSLaunchApplication = dlsym(h, "SBSLaunchApplication");
p_SBSApplicationLaunchingErrorString = dlsym(h, "SBSApplicationLaunchingErrorString");
p_SBSCopyFrontmostApplicationDisplayIdentifier = dlsym(h, "SBSCopyFrontmostApplicationDisplayIdentifier");
@@ -350,6 +356,26 @@ static void cfstr(CFStringRef s, char *out, size_t len)
if (s) CFStringGetCString(s, out, len, kCFStringEncodingUTF8);
}
/* API MIG du firmware 2.2.1 : les deux états sont des octets, retour kern_return_t. */
static void cmd_screen(int fd, int wake)
{
load_sbs();
if (!p_SBSSpringBoardServerPort || !p_SBGetScreenLockStatus || !p_SBDimScreen) {
reply_str(fd, 0, "API d'écran indisponible"); return;
}
unsigned port = p_SBSSpringBoardServerPort();
unsigned char locked = 0, passcode = 0;
int rc = p_SBGetScreenLockStatus(port, &locked, &passcode);
if (rc) { reply_str(fd, 0, "SBGetScreenLockStatus : %d", rc); return; }
if (wake) {
/* SBApplicationRequestedDeviceUnlock affiche le clavier de code même
sans code activé. Réveiller seulement l'écran, puis glisser côté hôte. */
rc = p_SBDimScreen(port, 0);
if (rc) { reply_str(fd, 0, "SBDimScreen : %d", rc); return; }
}
reply_str(fd, 1, "locked=%u passcode=%u", locked, passcode);
}
static void cmd_launch(int fd, char **args, int nargs)
{
load_sbs();
@@ -710,6 +736,8 @@ static void handle(int fd, char *line)
else if (!strcmp(cmd, "exec")) cmd_exec(fd, a, na);
else if (!strcmp(cmd, "launch")) cmd_launch(fd, a, na);
else if (!strcmp(cmd, "front")) cmd_front(fd);
else if (!strcmp(cmd, "screen")) cmd_screen(fd, 0);
else if (!strcmp(cmd, "wake")) cmd_screen(fd, 1);
else if (!strcmp(cmd, "fetch")) cmd_fetch(fd, a, na);
else if (!strcmp(cmd, "sc")) cmd_sc(fd, a, na);
else if (!strcmp(cmd, "routes")) cmd_routes(fd);
@@ -733,7 +761,7 @@ static void handle(int fd, char *line)
else if (!strcmp(cmd, "net")) cmd_net(fd);
else if (!strcmp(cmd, "respring")) reply_str(fd, kill_by_name("SpringBoard", SIGTERM) > 0, "SpringBoard relancé");
else if (!strcmp(cmd, "sync")) { sync(); reply_str(fd, 1, "ok"); }
else reply_str(fd, 0, "commande inconnue : %s (ping exec launch fetch sc routes settime front apps put get ls rm mkdir ps kill net respring sync)", cmd);
else reply_str(fd, 0, "commande inconnue : %s (ping exec launch fetch sc routes settime screen wake front apps put get ls rm mkdir ps kill net respring sync)", cmd);
}
static void serve_client(int fd)
+57 -3
View File
@@ -7,6 +7,8 @@
lance une app (stdout/stderr, donc NSLog, dans F sur l'iPod ; URL à ouvrir)
ipod-agent fetch http://hôte/chemin requête HTTP depuis l'iPod (test réseau : DNS + TCP)
ipod-agent front app au premier plan
ipod-agent screen | wake état du verrouillage / réveil sans clavier de code (agent v11)
ipod-agent unlock réveille puis glisse et vérifie le déverrouillage (sans code)
ipod-agent exec PROG [ARGS...] exécute un programme (pas de shell : chemin absolu)
ipod-agent ps | net | respring | sync
ipod-agent kill PID|NOM [SIGNAL]
@@ -51,15 +53,63 @@ def out(body):
sys.stdout.buffer.write(b"\n")
def emu_home():
tools_home = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
default_home = tools_home if os.path.isdir(os.path.join(tools_home, "images")) else os.path.expanduser("~/ipod-emu")
return os.environ.get("IPOD_EMU_HOME", default_home)
def unlock(a):
def screen():
ok, body, _ = a.call("screen")
if not ok:
sys.exit("État d'écran indisponible (agent v11 requis) : " + body.decode())
return dict(field.split("=", 1) for field in body.decode().split())
state = screen()
if state.get("locked") == "0":
print("Écran déverrouillé")
return
if state.get("passcode") != "0":
sys.exit("Un code de verrouillage est activé : déverrouiller manuellement.")
# Le pilote tactile doit avoir terminé son démarrage avant tout glissement.
try:
with open(os.path.join(emu_home(), "run", "serial.log"), "rb") as f:
serial = f.read()
except OSError as e:
sys.exit(f"Console de session inaccessible : {e}")
helper_ready = any(b"SCHelper" in line and b'"EXIT"' in line for line in serial.splitlines())
if serial.count(b"AppleMultitouchSPIUserClient::attach") < 2 or not helper_ready:
sys.exit("Contrôleur tactile pas encore prêt : attendre ipod-emu wait.")
qmp = os.path.join(os.path.dirname(os.path.abspath(__file__)), "ipod-qmp")
sock = os.environ.get("IPOD_QMP", os.path.join(emu_home(), "run", "qmp.sock"))
for attempt in range(3):
ok, body, _ = a.call("wake")
if not ok:
sys.exit(body.decode())
time.sleep(2) # laisser le pilote réactiver l'écran et le tactile
# La surface tactile émulée est légèrement plus petite que l'écran :
# le geste doit atteindre le bord droit pour terminer le déverrouillage.
subprocess.run([qmp, "-s", sock, "swipe", "60", "450", "319", "450"], check=True)
time.sleep(2)
state = screen()
if state.get("locked") == "0":
print("Écran déverrouillé")
return
if state.get("passcode") != "0":
sys.exit("Un code de verrouillage est activé : déverrouiller manuellement.")
sys.exit("Écran toujours verrouillé après trois glissements.")
def push_app(a, app):
emu_home = os.environ.get("IPOD_EMU_HOME", os.path.expanduser("~/ipod-emu"))
run = os.path.join(emu_home, "run")
home = emu_home()
run = os.path.join(home, "run")
try:
with open(os.path.join(run, "nand", ".ipod-nand-format")) as f:
layout = f.read().strip()
with open(os.path.join(run, "fw")) as f:
firmware = f.read().strip()
with open(os.path.join(emu_home, "images", firmware, "machine-opts")) as f:
with open(os.path.join(home, "images", firmware, "machine-opts")) as f:
machine_opts = f.read()
except OSError:
sys.exit("push-app nécessite une image locale avec persistance NAND (ipod-mkimage / ipod-build-fw).")
@@ -120,6 +170,10 @@ def main():
except OSError as e:
sys.exit(f"agent injoignable sur {HOST}:{PORT} ({e}) — ipod-netd lancé ?")
if cmd == "unlock":
a.s.settimeout(15)
unlock(a)
return
if cmd == "get":
ok, body, _ = a.call("get", rest[0])
if not ok:
+49 -8
View File
@@ -2,8 +2,13 @@
# Lance / arrête l'émulateur iPod Touch 2G (qemu-ios, N72AP).
set -euo pipefail
EMU_HOME="${IPOD_EMU_HOME:-$HOME/ipod-emu}"
QEMU="${IPOD_QEMU:-$HOME/qemu-ios/build/qemu-system-arm}"
TOOLS_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)
DEFAULT_EMU_HOME="$HOME/ipod-emu"
# Les outils peuvent être utilisés directement depuis un home de toolchain déplacé.
[ ! -d "$TOOLS_DIR/../images" ] || DEFAULT_EMU_HOME=$(cd "$TOOLS_DIR/.." && pwd)
EMU_HOME="${IPOD_EMU_HOME:-$DEFAULT_EMU_HOME}"
QEMU="${IPOD_QEMU:-$(dirname "$EMU_HOME")/qemu-ios/build/qemu-system-arm}"
QEMU_DATA="${IPOD_QEMU_DATA:-$(dirname "$(dirname "$QEMU")")/pc-bios}"
FW="${IPOD_FW:-5H11a}" # dossier $EMU_HOME/images/<FW>/ : bootrom, nor.bin, nand/ (5H11a = 2.2.1, 5F138 = 2.1.1)
RUN="$EMU_HOME/run"
VNC="${IPOD_VNC:-127.0.0.1:0}" # :0 => port 5900
@@ -39,7 +44,9 @@ wait_ready() {
[ $((SECONDS - s)) -lt "$t" ] || { echo "Timeout : SpringBoard pas prêt après ${t}s" >&2; return 1; }
sleep 2
done
sleep 3; echo "SpringBoard prêt ($((SECONDS - s)) s)"
sleep 3
"$(dirname "$0")/ipod-agent" unlock
echo "SpringBoard prêt et déverrouillé ($((SECONDS - s)) s)"
}
pid() { [ -f "$RUN/qemu.pid" ] && kill -0 "$(cat "$RUN/qemu.pid")" 2>/dev/null && cat "$RUN/qemu.pid"; }
@@ -61,11 +68,22 @@ start)
while getopts "fWw:" o; do case $o in f) fresh=1 ;; W) waitr=1 ;; w) FW=$OPTARG ;; *) usage 1 ;; esac; done
img="$EMU_HOME/images/$FW"
[ -d "$img" ] || { echo "Firmware inconnu : $img" >&2; exit 1; }
[ -z "$(pid)" ] || { echo "Déjà lancé (pid $(pid))"; exit 0; }
if [ -n "$(pid)" ]; then
echo "Déjà lancé (pid $(pid))"
[ $waitr = 0 ] || wait_ready
exit 0
fi
[ -x "$QEMU" ] || { echo "QEMU introuvable : $QEMU (définir IPOD_QEMU)" >&2; exit 1; }
[ -r "$img/bootrom" ] || { echo "BootROM introuvable : $img/bootrom (vérifier les liens après déplacement du home)" >&2; exit 1; }
[ -x "$EMU_HOME/netd/ipod-netd" ] || { echo "Relais réseau introuvable : $EMU_HOME/netd/ipod-netd" >&2; exit 1; }
"$QEMU" --version >/dev/null
qemu_data_args=()
[ ! -d "$QEMU_DATA/keymaps" ] || qemu_data_args=(-L "$QEMU_DATA")
mkdir -p "$RUN"
if [ $fresh = 1 ] || [ ! -d "$RUN/nand" ] || [ "$(cat "$RUN/fw" 2>/dev/null)" != "$FW" ]; then
rm -rf "$RUN/nand"; cp -rL "$img/nand" "$RUN/nand"; echo "$FW" > "$RUN/fw"
fi
stop_netd
rm -f "$RUN/qmp.sock" "$RUN/serial.log"
mopts=$(cat "$img/machine-opts" 2>/dev/null || true) # ex. ",legacy-nor=off"
if [[ "$mopts" == *",nand-write=on"* ]] &&
@@ -74,21 +92,44 @@ start)
exit 1
fi
nohup setsid "$QEMU" -M "iPod-Touch,bootrom=$img/bootrom,nand=$RUN/nand,nor=$img/nor.bin$mopts" \
-cpu max -m 2G -serial "file:$RUN/serial.log" -serial "unix:$RUN/uart1.sock,server=on,wait=off" \
"${qemu_data_args[@]}" -cpu max -m 2G -serial "file:$RUN/serial.log" -serial "unix:$RUN/uart1.sock,server=on,wait=off" \
-display none -vnc "$VNC" -qmp "unix:$RUN/qmp.sock,server,nowait" \
-pidfile "$RUN/qemu.pid" ${IPOD_QEMU_EXTRA:-} > "$RUN/qemu.log" 2>&1 &
for _ in $(seq 50); do [ -S "$RUN/qmp.sock" ] && break; sleep 0.2; done
qemu_pid=$!
for _ in $(seq 50); do
if ! kill -0 "$qemu_pid" 2>/dev/null; then
echo "Échec du démarrage de QEMU :" >&2
cat "$RUN/qemu.log" >&2
exit 1
fi
[ ! -S "$RUN/qmp.sock" ] || [ -z "$(pid)" ] || break
sleep 0.2
done
if [ ! -S "$RUN/qmp.sock" ] || [ -z "$(pid)" ]; then
kill "$qemu_pid" 2>/dev/null || true
echo "QEMU n'a pas ouvert son socket QMP (voir $RUN/qemu.log)" >&2
exit 1
fi
# réseau : PPP sur l'UART1 -> slirp (NAT, DNS, 127.0.0.1:7788 -> agent de l'iPod)
stop_netd
nohup setsid "$EMU_HOME/netd/ipod-netd" -s "$RUN/uart1.sock" ${IPOD_NETD_FWD:-} > "$RUN/netd.log" 2>&1 &
echo "$!" > "$RUN/netd.pid"
netd_pid=$!
echo "$netd_pid" > "$RUN/netd.pid"
sleep 0.3
if ! kill -0 "$netd_pid" 2>/dev/null; then
echo "Échec du relais réseau :" >&2
cat "$RUN/netd.log" >&2
"$(dirname "$0")/ipod-qmp" -s "$RUN/qmp.sock" quit 2>/dev/null || kill "$qemu_pid"
stop_netd
exit 1
fi
echo "Démarré ($FW) — pid $(pid), VNC $VNC. SpringBoard apparaît en ~1 min."
echo "Logs iOS : $RUN/serial.log"
[ $waitr = 0 ] || wait_ready
;;
wait) wait_ready "${1:-300}" ;;
stop)
p=$(pid) || { echo "Pas lancé"; exit 0; }
p=$(pid) || { stop_netd; echo "Pas lancé"; exit 0; }
"$(dirname "$0")/ipod-qmp" -s "$RUN/qmp.sock" quit 2>/dev/null || kill "$p"
for _ in $(seq 50); do kill -0 "$p" 2>/dev/null || break; sleep 0.2; done
kill -0 "$p" 2>/dev/null && kill -9 "$p"
+4 -1
View File
@@ -59,7 +59,10 @@ def key(q, qcode):
def main():
p = argparse.ArgumentParser(usage=__doc__)
p.add_argument("-s", "--sock", default=os.environ.get("IPOD_QMP", os.path.expanduser("~/ipod-emu/run/qmp.sock")))
tools_home = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
default_home = tools_home if os.path.isdir(os.path.join(tools_home, "images")) else os.path.expanduser("~/ipod-emu")
emu_home = os.environ.get("IPOD_EMU_HOME", default_home)
p.add_argument("-s", "--sock", default=os.environ.get("IPOD_QMP", os.path.join(emu_home, "run", "qmp.sock")))
p.add_argument("action")
p.add_argument("args", nargs="*")
a = p.parse_args()
+2
View File
@@ -556,6 +556,8 @@ static void add_fwd(const char *spec)
}
if (slirp_add_hostfwd(slirp, 0, host, hp, guest, gp) < 0) {
logm("redirection %s impossible (port occupé ?)", spec);
/* Ne pas laisser le client contacter le relais d'une autre session. */
exit(1);
} else {
logm("redirection tcp %s:%d -> iPod:%d", inet_ntoa(host), hp, gp);
}