mirror of
https://github.com/tihmstar/futurerestore.git
synced 2024-12-22 17:35:29 +00:00
added option to automatically load latest sep/baseband (untested)
This commit is contained in:
parent
8c08fb0a29
commit
20851cc697
|
@ -21,10 +21,20 @@
|
|||
#include "ipsw.h"
|
||||
#include "locking.h"
|
||||
#include "restore.h"
|
||||
#include "tsschecker.h"
|
||||
|
||||
#define NONCESIZE 20
|
||||
#define USEC_PER_SEC 1000000
|
||||
|
||||
#define TMP_PATH "/tmp"
|
||||
#define FUTURERESTORE_TMP_PATH TMP_PATH"/futurerestore"
|
||||
|
||||
#define BASEBAND_TMP_PATH FUTURERESTORE_TMP_PATH"/baseband.bbfw"
|
||||
#define BASEBAND_MANIFEST_TMP_PATH FUTURERESTORE_TMP_PATH"/basebandManifest.plist"
|
||||
#define SEP_TMP_PATH FUTURERESTORE_TMP_PATH"/sep.im4p"
|
||||
#define SEP_MANIFEST_TMP_PATH FUTURERESTORE_TMP_PATH"/sepManifest.plist"
|
||||
|
||||
|
||||
#define reterror(code,msg ...) error(msg),throw int(code)
|
||||
#define safeFree(buf) if (buf) free(buf), buf = NULL
|
||||
#define safePlistFree(buf) if (buf) plist_free(buf), buf = NULL
|
||||
|
@ -32,9 +42,12 @@
|
|||
futurerestore::futurerestore(){
|
||||
_client = idevicerestore_client_new();
|
||||
if (_client == NULL) throw std::string("could not create idevicerestore client\n");
|
||||
_didInit = false;
|
||||
_apticket = NULL;
|
||||
_im4m = NULL;
|
||||
|
||||
struct stat st{0};
|
||||
if (stat(FUTURERESTORE_TMP_PATH, &st) == -1) mkdir(FUTURERESTORE_TMP_PATH, 0755);
|
||||
|
||||
//tsschecker nocache
|
||||
nocache = 1;
|
||||
}
|
||||
|
||||
bool futurerestore::init(){
|
||||
|
@ -441,11 +454,102 @@ error:
|
|||
futurerestore::~futurerestore(){
|
||||
idevicerestore_client_free(_client);
|
||||
safeFree(_im4m);
|
||||
safeFree(_firmwareJson);
|
||||
safeFree(_firmwareTokens);
|
||||
safeFree(__latestManifest);
|
||||
safeFree(__latestFirmwareUrl);
|
||||
safePlistFree(_apticket);
|
||||
}
|
||||
|
||||
void futurerestore::loadFirmwareTokens(){
|
||||
if (_firmwareTokens){
|
||||
if (!_firmwareJson) _firmwareJson = getFirmwareJson();
|
||||
if (!_firmwareJson) reterror(-6,"[TSSC] could not get firmware.json\n");
|
||||
int cnt = parseTokens(_firmwareJson, &_firmwareTokens);
|
||||
if (cnt < 1) reterror(-2,"[TSSC] parsing %s.json failed\n",(0) ? "ota" : "firmware");
|
||||
}
|
||||
}
|
||||
|
||||
const char *futurerestore::getConnectedDeviceModel(){
|
||||
if (!_client->device->hardware_model){
|
||||
|
||||
int mode = getDeviceMode(true);
|
||||
if (mode != MODE_NORMAL && mode != MODE_RECOVERY)
|
||||
reterror(-20, "unexpected device mode=%d\n",mode);
|
||||
|
||||
if (check_hardware_model(_client) == NULL || _client->device == NULL)
|
||||
reterror(-2,"ERROR: Unable to discover device model\n");
|
||||
}
|
||||
|
||||
return _client->device->hardware_model;
|
||||
}
|
||||
|
||||
char *futurerestore::getLatestManifest(){
|
||||
if (!__latestManifest){
|
||||
loadFirmwareTokens();
|
||||
|
||||
const char *device = getConnectedDeviceModel();
|
||||
t_iosVersion versVals;
|
||||
memset(&versVals, 0, sizeof(versVals));
|
||||
|
||||
int versionCnt = 0;
|
||||
int i = 0;
|
||||
char **versions = getListOfiOSForDevice(_firmwareJson, _firmwareTokens, device, 0, &versionCnt);
|
||||
if (!versionCnt) reterror(-8, "[TSSC] failed finding latest iOS\n");
|
||||
char *bpos = NULL;
|
||||
while((bpos = strstr(versVals.version = strdup(versions[i++]),"[B]")) != 0){
|
||||
free((char*)versVals.version);
|
||||
if (--versionCnt == 0) reterror(-9, "[TSSC] automatic iOS selection couldn't find non-beta iOS\n");
|
||||
}
|
||||
info("[TSSC] selecting latest iOS: %s\n",versVals.version);
|
||||
if (bpos) *bpos= '\0';
|
||||
if (versions) free(versions[versionCnt-1]),free(versions);
|
||||
|
||||
__latestFirmwareUrl = getFirmwareUrl(device, versVals, _firmwareJson, _firmwareTokens);
|
||||
if (!__latestFirmwareUrl) reterror(-21, "could not find url of latest firmware\n");
|
||||
__latestManifest = getBuildManifest(__latestFirmwareUrl, device, versVals.version, 0);
|
||||
if (!__latestManifest) reterror(-22, "could not get buildmanifest of latest firmware\n");
|
||||
free((char*)versVals.version);
|
||||
}
|
||||
|
||||
return __latestManifest;
|
||||
}
|
||||
|
||||
char *futurerestore::getLatestFirmwareUrl(){
|
||||
return getLatestManifest(),__latestFirmwareUrl;
|
||||
}
|
||||
|
||||
|
||||
void futurerestore::loadLatestBaseband(){
|
||||
char * manifeststr = getLatestManifest();
|
||||
char *pathStr = getPathOfElementInManifest("BasebandFirmware", manifeststr);
|
||||
if (!downloadPartialzip(getLatestFirmwareUrl(), pathStr, _basebandPath = BASEBAND_TMP_PATH))
|
||||
reterror(-32, "could not download baseband\n");
|
||||
saveStringToFile(manifeststr, _basebandManifestPath = BASEBAND_MANIFEST_TMP_PATH);
|
||||
}
|
||||
|
||||
void futurerestore::loadLatestSep(){
|
||||
char * manifeststr = getLatestManifest();
|
||||
char *pathStr = getPathOfElementInManifest("SEP", manifeststr);
|
||||
if (!downloadPartialzip(getLatestFirmwareUrl(), pathStr, _sepPath = SEP_TMP_PATH))
|
||||
reterror(-33, "could not download SEP\n");
|
||||
saveStringToFile(manifeststr, _sepManifestPath = SEP_MANIFEST_TMP_PATH);
|
||||
}
|
||||
|
||||
|
||||
#pragma mark static methods
|
||||
|
||||
inline void futurerestore::saveStringToFile(const char *str, const char *path){
|
||||
FILE *f = fopen(path, "w");
|
||||
if (!f) reterror(-41,"can't save file at %s\n",path);
|
||||
else{
|
||||
size_t len = strlen(str);
|
||||
size_t wlen = fwrite(str, len, 1, f);
|
||||
fclose(f);
|
||||
if (len != wlen) reterror(-42, "saving file failed, wrote=%zu actual=%zu\n",wlen,len);
|
||||
}
|
||||
}
|
||||
|
||||
char *futurerestore::getNonceFromIM4M(const char* im4m){
|
||||
char *ret = NULL;
|
||||
t_asn1Tag *mainSet = NULL;
|
||||
|
@ -536,3 +640,22 @@ plist_t futurerestore::loadPlistFromFile(const char *path){
|
|||
return ret;
|
||||
}
|
||||
|
||||
char *futurerestore::getPathOfElementInManifest(const char *element, const char *manifeststr){
|
||||
char *pathStr = NULL;
|
||||
|
||||
plist_t buildmanifest;
|
||||
plist_from_xml(manifeststr, (uint)strlen(manifeststr), &buildmanifest);
|
||||
|
||||
if (plist_t buildidentities = plist_dict_get_item(buildmanifest, "BuildIdentities"))
|
||||
if (plist_t firstIdentitie = plist_array_get_item(buildidentities, 0))
|
||||
if (plist_t manifest = plist_dict_get_item(firstIdentitie, element))
|
||||
if (plist_t info = plist_dict_get_item(manifest, "Info"))
|
||||
if (plist_t path = plist_dict_get_item(info, "Path"))
|
||||
if (plist_get_string_val(path, &pathStr), pathStr)
|
||||
goto noerror;
|
||||
reterror(-31, "could not get %s path\n",element);
|
||||
noerror:
|
||||
plist_free(buildmanifest);
|
||||
return pathStr;
|
||||
}
|
||||
|
||||
|
|
|
@ -12,19 +12,26 @@
|
|||
#include "config.h"
|
||||
#include <stdio.h>
|
||||
#include "idevicerestore.h"
|
||||
#include "jsmn.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
class futurerestore {
|
||||
struct idevicerestore_client_t* _client;
|
||||
bool _didInit;
|
||||
plist_t _apticket;
|
||||
char *_im4m;
|
||||
bool _didInit = false;
|
||||
plist_t _apticket = NULL;
|
||||
char *_im4m = NULL;
|
||||
|
||||
char *_firmwareJson = NULL;
|
||||
jsmntok_t *_firmwareTokens = NULL;;
|
||||
char *__latestManifest = NULL;
|
||||
char *__latestFirmwareUrl = NULL;
|
||||
|
||||
const char *_sepManifestPath = NULL;
|
||||
const char *_basebandManifestPath = NULL;
|
||||
const char *_sepPath = NULL;
|
||||
const char *_basebandPath = NULL;
|
||||
|
||||
const char *_sepManifestPath;
|
||||
const char *_basebandManifestPath;
|
||||
const char *_sepPath;
|
||||
const char *_basebandPath;
|
||||
|
||||
public:
|
||||
futurerestore();
|
||||
|
@ -40,12 +47,25 @@ public:
|
|||
|
||||
bool nonceMatchesApTicket();
|
||||
|
||||
void loadFirmwareTokens();
|
||||
const char *getConnectedDeviceModel();
|
||||
char *getLatestManifest();
|
||||
char *getLatestFirmwareUrl();
|
||||
void loadLatestBaseband();
|
||||
void loadLatestSep();
|
||||
|
||||
void setSepManifestPath(const char *sepManifestPath){_sepManifestPath = sepManifestPath;};
|
||||
void setBasebandManifestPath(const char *basebandManifestPath){_basebandManifestPath = basebandManifestPath;};
|
||||
void setSepPath(const char *sepPath){_sepPath = sepPath;};
|
||||
void setBasebandPath(const char *basebandPath){_basebandPath = basebandPath;};
|
||||
|
||||
|
||||
const char *sepManifestPath(){return _sepManifestPath;};
|
||||
const char *basebandManifestPath(){return _basebandManifestPath;};
|
||||
const char *sepPath(){return _sepPath;};
|
||||
const char *basebandPath(){return _basebandPath;};
|
||||
|
||||
|
||||
int doRestore(const char *ipsw, bool noerase);
|
||||
|
||||
~futurerestore();
|
||||
|
@ -53,6 +73,8 @@ public:
|
|||
static char *getNonceFromIM4M(const char* im4m);
|
||||
static char *getNonceFromAPTicket(const char* apticketPath);
|
||||
static plist_t loadPlistFromFile(const char *path);
|
||||
static void saveStringToFile(const char *str, const char *path);
|
||||
static char *getPathOfElementInManifest(const char *element, const char *manifeststr);
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -16,19 +16,23 @@
|
|||
#define safePlistFree(buf) if (buf) plist_free(buf), buf = NULL
|
||||
|
||||
static struct option longopts[] = {
|
||||
{ "apticket", required_argument, NULL, 't' },
|
||||
{ "baseband", required_argument, NULL, 'b' },
|
||||
{ "baseband-plist", required_argument, NULL, 'p' },
|
||||
{ "sep", required_argument, NULL, 's' },
|
||||
{ "sep-manifest", required_argument, NULL, 'm' },
|
||||
{ "wait", no_argument, NULL, 'w' },
|
||||
{ "update", no_argument, NULL, 'u' },
|
||||
{ "debug", no_argument, NULL, 'd' },
|
||||
{ "apticket", required_argument, NULL, 't' },
|
||||
{ "baseband", required_argument, NULL, 'b' },
|
||||
{ "baseband-plist", required_argument, NULL, 'p' },
|
||||
{ "sep", required_argument, NULL, 's' },
|
||||
{ "sep-manifest", required_argument, NULL, 'm' },
|
||||
{ "wait", no_argument, NULL, 'w' },
|
||||
{ "update", no_argument, NULL, 'u' },
|
||||
{ "debug", no_argument, NULL, 'd' },
|
||||
{ "latest-sep", no_argument, NULL, '0' },
|
||||
{ "latest-baseband", no_argument, NULL, '1' },
|
||||
{ NULL, 0, NULL, 0 }
|
||||
};
|
||||
|
||||
#define FLAG_WAIT 1 << 0
|
||||
#define FLAG_UPDATE 1 << 1
|
||||
#define FLAG_WAIT 1 << 0
|
||||
#define FLAG_UPDATE 1 << 1
|
||||
#define FLAG_LATEST_SEP 1 << 2
|
||||
#define FLAG_LATEST_BASEBAND 1 << 3
|
||||
|
||||
void cmd_help(){
|
||||
printf("Usage: futurerestore [OPTIONS] IPSW\n");
|
||||
|
@ -75,7 +79,7 @@ int main(int argc, const char * argv[]) {
|
|||
return -1;
|
||||
}
|
||||
|
||||
while ((opt = getopt_long(argc, (char* const *)argv, "ht:b:p:s:m:wud", longopts, &optindex)) > 0) {
|
||||
while ((opt = getopt_long(argc, (char* const *)argv, "ht:b:p:s:m:wud01", longopts, &optindex)) > 0) {
|
||||
switch (opt) {
|
||||
case 't': // long option: "apticket"; can be called as short option
|
||||
apticketPath = optarg;
|
||||
|
@ -98,6 +102,12 @@ int main(int argc, const char * argv[]) {
|
|||
case 'u': // long option: "update"; can be called as short option
|
||||
flags |= FLAG_UPDATE;
|
||||
break;
|
||||
case '0': // long option: "latest-sep";
|
||||
flags |= FLAG_LATEST_SEP;
|
||||
break;
|
||||
case '1': // long option: "latest-baseband";
|
||||
flags |= FLAG_LATEST_BASEBAND;
|
||||
break;
|
||||
case 'd': // long option: "debug"; can be called as short option
|
||||
idevicerestore_debug = 1;
|
||||
break;
|
||||
|
@ -122,7 +132,9 @@ int main(int argc, const char * argv[]) {
|
|||
client.putDeviceIntoRecovery();
|
||||
client.waitForNonce();
|
||||
}
|
||||
if (!(apticketPath && basebandPath && basebandManifestPath && sepPath && sepManifestPath && ipsw)) {
|
||||
if (!(apticketPath && ipsw)
|
||||
&& ((basebandPath && basebandManifestPath) || (flags & FLAG_LATEST_BASEBAND))
|
||||
&& ((sepPath && sepManifestPath) || (flags & FLAG_LATEST_SEP)) ) {
|
||||
if (!(flags & FLAG_WAIT) || ipsw){
|
||||
error("missing argument\n");
|
||||
cmd_help();
|
||||
|
@ -134,22 +146,28 @@ int main(int argc, const char * argv[]) {
|
|||
}
|
||||
|
||||
|
||||
if (flags & FLAG_LATEST_SEP) client.loadLatestSep();
|
||||
else{
|
||||
client.setSepPath(sepPath);
|
||||
client.setSepManifestPath(sepManifestPath);
|
||||
}
|
||||
if (flags & FLAG_LATEST_BASEBAND) client.loadLatestBaseband();
|
||||
else{
|
||||
client.setBasebandPath(basebandPath);
|
||||
client.setBasebandManifestPath(basebandManifestPath);
|
||||
}
|
||||
|
||||
|
||||
versVals.basebandMode = kBasebandModeWithoutBaseband;
|
||||
if (!(isSepManifestSigned = isManifestSignedForDevice(sepManifestPath, NULL, devVals, versVals))){
|
||||
if (!(isSepManifestSigned = isManifestSignedForDevice(client.sepManifestPath(), NULL, devVals, versVals))){
|
||||
reterror(-3,"sep firmware isn't signed\n");
|
||||
}
|
||||
|
||||
versVals.basebandMode = kBasebandModeOnlyBaseband;
|
||||
if (!(isBasebandSigned = isManifestSignedForDevice(basebandManifestPath, NULL, devVals, versVals))){
|
||||
if (!(isBasebandSigned = isManifestSignedForDevice(client.basebandManifestPath(), NULL, devVals, versVals))){
|
||||
reterror(-3,"baseband firmware isn't signed\n");
|
||||
}
|
||||
|
||||
client.setSepPath(sepPath);
|
||||
client.setSepManifestPath(sepManifestPath);
|
||||
client.setBasebandPath(basebandPath);
|
||||
client.setBasebandManifestPath(basebandManifestPath);
|
||||
|
||||
|
||||
client.putDeviceIntoRecovery();
|
||||
|
||||
try {
|
||||
|
|
Loading…
Reference in a new issue