fixed up bug with header checksumming, also fixed warnings
This commit is contained in:
Родитель
9b7b3fedc1
Коммит
70448b939f
|
@ -577,7 +577,7 @@ void writeATAPI(AbstractFile* file, ChecksumFunc dataForkChecksum, void* dataFor
|
|||
memset(&uncompressedToken, 0, sizeof(uncompressedToken));
|
||||
|
||||
atapi = (char*) malloc(ATAPI_SIZE * SECTOR_SIZE);
|
||||
printf("malloc: %x %d\n", atapi, ATAPI_SIZE * SECTOR_SIZE); fflush(stdout);
|
||||
printf("malloc: %p %d\n", atapi, ATAPI_SIZE * SECTOR_SIZE); fflush(stdout);
|
||||
memcpy(atapi, atapi_data, ATAPI_SIZE * SECTOR_SIZE);
|
||||
bufferFile = createAbstractFileFromMemory((void**)&atapi, ATAPI_SIZE * SECTOR_SIZE);
|
||||
|
||||
|
|
|
@ -319,7 +319,7 @@ static void readResourceData(ResourceData* data, char** location, FlipDataFunc f
|
|||
sscanf(buffer, "%d", &(data->id));
|
||||
free(buffer);
|
||||
} else if(strncmp(tagBegin, "Name", strLen) == 0) {
|
||||
data->name = (unsigned char*) getXMLString(&curLoc);
|
||||
data->name = getXMLString(&curLoc);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -492,7 +492,7 @@ ResourceKey* writeNSiz(NSizResource* nSiz) {
|
|||
|
||||
curData->attributes = 0;
|
||||
curData->id = curNSiz->partitionNumber;
|
||||
curData->name = (unsigned char*) malloc(sizeof(char));
|
||||
curData->name = (char*) malloc(sizeof(char));
|
||||
curData->name[0] = '\0';
|
||||
curData->next = NULL;
|
||||
curData->dataLength = sizeof(char) * strlen(buffer);
|
||||
|
@ -810,7 +810,7 @@ ResourceKey* insertData(ResourceKey* resources, const char* key, int id, const c
|
|||
curData->attributes = attributes;
|
||||
curData->dataLength = dataLength;
|
||||
curData->id = id;
|
||||
curData->name = (unsigned char*) malloc(strlen(name) + 1);
|
||||
curData->name = (char*) malloc(strlen(name) + 1);
|
||||
strcpy((char*) curData->name, name);
|
||||
curData->data = (unsigned char*) malloc(dataLength);
|
||||
memcpy(curData->data, data, dataLength);
|
||||
|
|
|
@ -9,14 +9,12 @@
|
|||
#include <dmg/filevault.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <dirent.h>
|
||||
#include <dirent.h>
|
||||
#include "hfs/hfslib.h"
|
||||
|
||||
char endianness;
|
||||
|
||||
void cmd_ls(Volume* volume, int argc, const char *argv[]) {
|
||||
HFSPlusCatalogRecord* record;
|
||||
char* name;
|
||||
|
||||
void cmd_ls(Volume* volume, int argc, const char *argv[]) {
|
||||
if(argc > 1)
|
||||
hfs_ls(volume, argv[1]);
|
||||
else
|
||||
|
|
|
@ -184,10 +184,6 @@ static int catalogCompare(BTKey* vLeft, BTKey* vRight) {
|
|||
static int catalogCompareCS(BTKey* vLeft, BTKey* vRight) {
|
||||
HFSPlusCatalogKey* left;
|
||||
HFSPlusCatalogKey* right;
|
||||
uint16_t i;
|
||||
|
||||
uint16_t cLeft;
|
||||
uint16_t cRight;
|
||||
|
||||
left = (HFSPlusCatalogKey*) vLeft;
|
||||
right =(HFSPlusCatalogKey*) vRight;
|
||||
|
@ -738,12 +734,9 @@ int move(const char* source, const char* dest, Volume* volume) {
|
|||
|
||||
int removeFile(const char* fileName, Volume* volume) {
|
||||
HFSPlusCatalogRecord* record;
|
||||
HFSPlusCatalogRecord* parentRecord;
|
||||
HFSPlusCatalogKey key;
|
||||
HFSPlusCatalogKey parentKey;
|
||||
io_func* io;
|
||||
HFSPlusCatalogFolder* parentFolder;
|
||||
int exact;
|
||||
|
||||
record = getRecordFromPath3(fileName, volume, NULL, &key, TRUE, FALSE, kHFSRootFolderID);
|
||||
if(record != NULL) {
|
||||
|
|
|
@ -13,9 +13,6 @@ char endianness;
|
|||
|
||||
|
||||
void cmd_ls(Volume* volume, int argc, const char *argv[]) {
|
||||
HFSPlusCatalogRecord* record;
|
||||
char* name;
|
||||
|
||||
if(argc > 1)
|
||||
hfs_ls(volume, argv[1]);
|
||||
else
|
||||
|
@ -283,7 +280,7 @@ int main(int argc, const char *argv[]) {
|
|||
} else if(strcmp(argv[2], "grow") == 0) {
|
||||
cmd_grow(volume, argc - 2, argv + 2);
|
||||
} else if(strcmp(argv[2], "debug") == 0) {
|
||||
if(argc > 3 && argv[3] == "verbose") {
|
||||
if(argc > 3 && strcmp(argv[3], "verbose") == 0) {
|
||||
debugBTree(volume->catalogTree, TRUE);
|
||||
} else {
|
||||
debugBTree(volume->catalogTree, FALSE);
|
||||
|
|
|
@ -467,7 +467,7 @@ int copyAcrossVolumes(Volume* volume1, Volume* volume2, char* path1, char* path2
|
|||
printf("retrieving... "); fflush(stdout);
|
||||
get_hfs(volume1, path1, tmpFile);
|
||||
tmpFile->seek(tmpFile, 0);
|
||||
printf("writing (%lld)... ", tmpFile->getLength(tmpFile)); fflush(stdout);
|
||||
printf("writing (%ld)... ", tmpFile->getLength(tmpFile)); fflush(stdout);
|
||||
ret = add_hfs(volume2, tmpFile, path2);
|
||||
printf("done\n");
|
||||
|
||||
|
@ -526,7 +526,7 @@ void displayFileLSLine(HFSPlusCatalogFile* file, const char* name) {
|
|||
printf("%06o ", file->permissions.fileMode);
|
||||
printf("%3d ", file->permissions.ownerID);
|
||||
printf("%3d ", file->permissions.groupID);
|
||||
printf("%12d ", file->dataFork.logicalSize);
|
||||
printf("%12lld ", file->dataFork.logicalSize);
|
||||
fileTime = APPLE_TO_UNIX_TIME(file->contentModDate);
|
||||
date = localtime(&fileTime);
|
||||
if(date != NULL) {
|
||||
|
|
|
@ -215,7 +215,7 @@ typedef struct ResourceData {
|
|||
unsigned char* data;
|
||||
size_t dataLength;
|
||||
int id;
|
||||
unsigned char* name;
|
||||
char* name;
|
||||
struct ResourceData* next;
|
||||
} ResourceData;
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ typedef struct {
|
|||
|
||||
#define SIGNATURE_8900 0x38393030
|
||||
|
||||
static uint8_t key_0x837[] = {0x18, 0x84, 0x58, 0xA6, 0xD1, 0x50, 0x34, 0xDF, 0xE3, 0x86, 0xF2, 0x3B, 0x61, 0xD4, 0x37, 0x74};
|
||||
#define key_0x837 ((uint8_t[]){0x18, 0x84, 0x58, 0xA6, 0xD1, 0x50, 0x34, 0xDF, 0xE3, 0x86, 0xF2, 0x3B, 0x61, 0xD4, 0x37, 0x74})
|
||||
|
||||
typedef struct Info8900 {
|
||||
AbstractFile* file;
|
||||
|
|
|
@ -61,6 +61,7 @@ extern "C" {
|
|||
char* getXmlFromRoot(Dictionary* root);
|
||||
DictValue* getValueByKey(Dictionary* myself, const char* key);
|
||||
void addStringToArray(ArrayValue* array, char* str);
|
||||
void removeKey(Dictionary* dict, char* key);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -8,9 +8,11 @@
|
|||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
int patch(AbstractFile* in, AbstractFile* out, AbstractFile* patch);
|
||||
Dictionary* parseIPSW(const char* inputIPSW, const char* bundleRoot, char** bundlePath, OutputState** state);
|
||||
int doPatch(StringValue* patchValue, StringValue* fileValue, const char* bundlePath, OutputState** state);
|
||||
void doPatchInPlace(Volume* volume, const char* filePath, const char* patchPath);
|
||||
void fixupBootNeuterArgs(Volume* volume, char unlockBaseband, char selfDestruct, char use39, char use46);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include "common.h"
|
||||
#include <xpwn/8900.h>
|
||||
#include <xpwn/img2.h>
|
||||
#include <zlib.h>
|
||||
|
||||
void flipApple8900Header(Apple8900Header* header) {
|
||||
FLIPENDIAN(header->magic);
|
||||
|
@ -75,8 +76,7 @@ void close8900(AbstractFile* file) {
|
|||
((Img2Header*)info->buffer)->dataLenPadded = ((Img2Header*)info->buffer)->dataLenPadded % 16 == 0 ? ((Img2Header*)info->buffer)->dataLenPadded : ((((Img2Header*)info->buffer)->dataLenPadded/16) + 1) * 16;
|
||||
info->header.sizeOfData = ((Img2Header*)info->buffer)->dataLenPadded + sizeof(Img2Header);
|
||||
|
||||
cksum = 0;
|
||||
crc32(&cksum, (unsigned char *)info->buffer, 0x64);
|
||||
cksum = crc32(0, (unsigned char *)info->buffer, 0x64);
|
||||
FLIPENDIANLE(cksum);
|
||||
((Img2Header*)info->buffer)->header_checksum = cksum;
|
||||
}
|
||||
|
|
|
@ -48,7 +48,7 @@ size_t bzRead(int *bzerr, BZStream* stream, unsigned char* out, size_t len) {
|
|||
haveRead = stream->file->read(stream->file, stream->inBuffer + stream->bz2.avail_in, stream->bufferLen - stream->bz2.avail_in);
|
||||
stream->offset += haveRead;
|
||||
stream->bz2.avail_in += haveRead;
|
||||
stream->bz2.next_in = stream->inBuffer;
|
||||
stream->bz2.next_in = (char*) stream->inBuffer;
|
||||
|
||||
*bzerr = BZ2_bzDecompress(&(stream->bz2));
|
||||
|
||||
|
@ -100,9 +100,9 @@ BZStream* openBZStream(AbstractFile* file, off_t offset, size_t bufferLen) {
|
|||
memset(&(stream->bz2), 0, sizeof(bz_stream));
|
||||
BZ2_bzDecompressInit(&(stream->bz2), 0, FALSE);
|
||||
|
||||
stream->bz2.next_in = stream->inBuffer;
|
||||
stream->bz2.next_in = (char*) stream->inBuffer;
|
||||
stream->bz2.avail_in = 0;
|
||||
stream->bz2.next_out = stream->outBuffer;
|
||||
stream->bz2.next_out = (char*) stream->outBuffer;
|
||||
stream->bz2.avail_out = bufferLen;
|
||||
|
||||
stream->ended = FALSE;
|
||||
|
|
|
@ -57,7 +57,6 @@ off_t getLengthIBootIM(AbstractFile* file) {
|
|||
|
||||
void closeIBootIM(AbstractFile* file) {
|
||||
InfoIBootIM* info = (InfoIBootIM*) (file->data);
|
||||
uint32_t cksum;
|
||||
uint8_t *compressed;
|
||||
if(info->dirty) {
|
||||
compressed = malloc(info->length * 2);
|
||||
|
@ -143,7 +142,6 @@ AbstractFile* createAbstractFileFromIBootIM(AbstractFile* file) {
|
|||
|
||||
AbstractFile* duplicateIBootIMFile(AbstractFile* file, AbstractFile* backing) {
|
||||
InfoIBootIM* info;
|
||||
unsigned char* copyCertificate;
|
||||
AbstractFile* toReturn;
|
||||
|
||||
if(!file) {
|
||||
|
@ -184,7 +182,7 @@ void pngError(png_structp png_ptr, png_const_charp error_msg) {
|
|||
|
||||
void* replaceBootImage(AbstractFile* imageWrapper, AbstractFile* png, size_t *fileSize) {
|
||||
AbstractFile* imageFile;
|
||||
char header[8];
|
||||
unsigned char header[8];
|
||||
InfoIBootIM* info;
|
||||
png_uint_32 i;
|
||||
png_bytepp row_pointers;
|
||||
|
@ -252,7 +250,7 @@ void* replaceBootImage(AbstractFile* imageWrapper, AbstractFile* png, size_t *fi
|
|||
|
||||
|
||||
if(info_ptr->width > 320 || info_ptr->height > 480) {
|
||||
printf("error: dimensions out of range, must be within 320x480, not %dx%d\n", info_ptr->width, info_ptr->height);
|
||||
printf("error: dimensions out of range, must be within 320x480, not %lux%lu\n", info_ptr->width, info_ptr->height);
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include "common.h"
|
||||
#include "abstractfile.h"
|
||||
#include <xpwn/img2.h>
|
||||
#include <zlib.h>
|
||||
|
||||
void flipImg2Header(Img2Header* header) {
|
||||
FLIPENDIANLE(header->signature);
|
||||
|
@ -70,8 +71,7 @@ void closeImg2(AbstractFile* file) {
|
|||
|
||||
flipImg2Header(&(info->header));
|
||||
|
||||
cksum = 0;
|
||||
crc32(&cksum, (unsigned char *)&(info->header), 0x64);
|
||||
cksum = crc32(0, (unsigned char *)&(info->header), 0x64);
|
||||
FLIPENDIANLE(cksum);
|
||||
info->header.header_checksum = cksum;
|
||||
|
||||
|
@ -124,7 +124,6 @@ AbstractFile* createAbstractFileFromImg2(AbstractFile* file) {
|
|||
|
||||
AbstractFile* duplicateImg2File(AbstractFile* file, AbstractFile* backing) {
|
||||
InfoImg2* info;
|
||||
unsigned char* copyCertificate;
|
||||
AbstractFile* toReturn;
|
||||
|
||||
if(!file) {
|
||||
|
|
|
@ -62,7 +62,6 @@ off_t getLengthImg3(AbstractFile* file) {
|
|||
}
|
||||
|
||||
void closeImg3(AbstractFile* file) {
|
||||
int i;
|
||||
Img3Info* info = (Img3Info*) file->data;
|
||||
|
||||
if(info->dirty) {
|
||||
|
|
|
@ -54,7 +54,6 @@ off_t getLengthComp(AbstractFile* file) {
|
|||
|
||||
void closeComp(AbstractFile* file) {
|
||||
InfoComp* info = (InfoComp*) (file->data);
|
||||
uint32_t cksum;
|
||||
uint8_t *compressed;
|
||||
if(info->dirty) {
|
||||
info->header.checksum = lzadler32((uint8_t*)info->buffer, info->header.length_uncompressed);
|
||||
|
@ -132,7 +131,6 @@ AbstractFile* createAbstractFileFromComp(AbstractFile* file) {
|
|||
|
||||
AbstractFile* duplicateCompFile(AbstractFile* file, AbstractFile* backing) {
|
||||
InfoComp* info;
|
||||
unsigned char* copyCertificate;
|
||||
AbstractFile* toReturn;
|
||||
|
||||
if(!file) {
|
||||
|
|
|
@ -61,8 +61,6 @@ int main(int argc, char* argv[]) {
|
|||
void* imageBuffer;
|
||||
size_t imageSize;
|
||||
|
||||
FILE* temp;
|
||||
|
||||
AbstractFile* bootloader39;
|
||||
AbstractFile* bootloader46;
|
||||
AbstractFile* applelogo;
|
||||
|
@ -288,7 +286,7 @@ int main(int argc, char* argv[]) {
|
|||
patchArray = (ArrayValue*) patchArray->dValue.next;
|
||||
}
|
||||
|
||||
for(mergePaths; mergePaths < argc; mergePaths++) {
|
||||
for(; mergePaths < argc; mergePaths++) {
|
||||
addall_hfs(rootVolume, argv[mergePaths], "/");
|
||||
}
|
||||
|
||||
|
|
|
@ -60,11 +60,7 @@ void addToOutputQueue(OutputState** state, char* fileName, void* buffer, size_t
|
|||
|
||||
void addToOutput(OutputState** state, char* fileName, void* buffer, size_t bufferSize) {
|
||||
char* fileNamePath;
|
||||
char* path;
|
||||
char* fileNameNoPath;
|
||||
char pathExists;
|
||||
OutputState* leftNeighbor;
|
||||
OutputState* rightNeighbor;
|
||||
|
||||
fileNamePath = (char*) malloc(sizeof(char) * (strlen(fileName) + 1));
|
||||
strcpy(fileNamePath, fileName);
|
||||
|
@ -196,7 +192,7 @@ OutputState* loadZip(const char* ipsw) {
|
|||
ASSERT(unzGetCurrentFileInfo(zip, NULL, fileName, pfile_info.size_filename + 1, NULL, 0, NULL, 0) == UNZ_OK, "cannot get current file name from ipsw");
|
||||
if(fileName[strlen(fileName) - 1] != '/') {
|
||||
buffer = malloc((pfile_info.uncompressed_size > 0) ? pfile_info.uncompressed_size : 1);
|
||||
printf("loading: %s (%d)\n", fileName, pfile_info.uncompressed_size); fflush(stdout);
|
||||
printf("loading: %s (%ld)\n", fileName, pfile_info.uncompressed_size); fflush(stdout);
|
||||
ASSERT(unzOpenCurrentFile(zip) == UNZ_OK, "cannot open compressed file in IPSW");
|
||||
ASSERT(unzReadCurrentFile(zip, buffer, pfile_info.uncompressed_size) == pfile_info.uncompressed_size, "cannot read file from ipsw");
|
||||
ASSERT(unzCloseCurrentFile(zip) == UNZ_OK, "cannot close compressed file in IPSW");
|
||||
|
|
|
@ -125,8 +125,6 @@ void createArray(ArrayValue* myself, char* xml) {
|
|||
Tag* valueTag;
|
||||
DictValue* curValue;
|
||||
|
||||
int i;
|
||||
|
||||
myself->values = NULL;
|
||||
myself->size = 0;
|
||||
while(*xml != '\0') {
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include <xpwn/outputstate.h>
|
||||
#include <xpwn/pwnutil.h>
|
||||
#include <xpwn/nor_files.h>
|
||||
#include <hfs/hfslib.h>
|
||||
|
||||
#define BUFFERSIZE (1024*1024)
|
||||
|
||||
|
@ -14,7 +15,6 @@ Dictionary* parseIPSW(const char* inputIPSW, const char* bundleRoot, char** bund
|
|||
Dictionary* info;
|
||||
char* infoPath;
|
||||
|
||||
char* ipswName;
|
||||
AbstractFile* plistFile;
|
||||
char* plist;
|
||||
FILE* inputIPSWFile;
|
||||
|
@ -22,7 +22,7 @@ Dictionary* parseIPSW(const char* inputIPSW, const char* bundleRoot, char** bund
|
|||
SHA_CTX sha1_ctx;
|
||||
char buffer[BUFFERSIZE];
|
||||
int read;
|
||||
char hash[20];
|
||||
unsigned char hash[20];
|
||||
|
||||
DIR* dir;
|
||||
struct dirent* ent;
|
||||
|
@ -74,7 +74,7 @@ Dictionary* parseIPSW(const char* inputIPSW, const char* bundleRoot, char** bund
|
|||
|
||||
plistSHA1String = (StringValue*)getValueByKey(info, "SHA1");
|
||||
if(plistSHA1String) {
|
||||
sscanf(plistSHA1String->value, "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
|
||||
sscanf(plistSHA1String->value, "%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx",
|
||||
&plistHash[0], &plistHash[1], &plistHash[2], &plistHash[3], &plistHash[4],
|
||||
&plistHash[5], &plistHash[6], &plistHash[7], &plistHash[8], &plistHash[9],
|
||||
&plistHash[10], &plistHash[11], &plistHash[12], &plistHash[13], &plistHash[14],
|
||||
|
@ -156,6 +156,8 @@ int doPatch(StringValue* patchValue, StringValue* fileValue, const char* bundleP
|
|||
printf("success\n"); fflush(stdout);
|
||||
|
||||
free(patchPath);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void doPatchInPlace(Volume* volume, const char* filePath, const char* patchPath) {
|
||||
|
|
|
@ -31,8 +31,9 @@ int main(int argc, char *argv[])
|
|||
StringValue* kernelValue;
|
||||
AbstractFile* ramdisk;
|
||||
|
||||
AbstractFile* applelogo;
|
||||
AbstractFile* recoverymode;
|
||||
AbstractFile* applelogo = NULL;
|
||||
AbstractFile* recoverymode = NULL;
|
||||
AbstractFile* iboot = NULL;
|
||||
int i;
|
||||
|
||||
TestByteOrder();
|
||||
|
@ -65,6 +66,15 @@ int main(int argc, char *argv[])
|
|||
i++;
|
||||
continue;
|
||||
}
|
||||
if(strcmp(argv[i], "-i") == 0) {
|
||||
iboot = createAbstractFileFromFile(fopen(argv[i + 1], "rb"));
|
||||
if(!iboot) {
|
||||
cout << "cannot open " << argv[i + 1] << endl;
|
||||
return 1;
|
||||
}
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
cout << " ... Connecting" << endl;
|
||||
|
@ -102,15 +112,20 @@ int main(int argc, char *argv[])
|
|||
exit(1);
|
||||
}
|
||||
|
||||
add_hfs(ramdiskVolume, getFileFromOutputState(&ipswContents, ((StringValue*)getValueByKey(ibootDict, "File"))->value), "/ipwner/iboot.img2");
|
||||
StringValue* patchValue = (StringValue*) getValueByKey(ibootDict, "Patch");
|
||||
char* patchPath = (char*) malloc(sizeof(char) * (strlen(bundlePath) + strlen(patchValue->value) + 2));
|
||||
strcpy(patchPath, bundlePath);
|
||||
strcat(patchPath, "/");
|
||||
strcat(patchPath, patchValue->value);
|
||||
printf("patching /ipwner/iboot.img2 (%s)... ", patchPath);
|
||||
doPatchInPlace(ramdiskVolume, "/ipwner/iboot.img2", patchPath);
|
||||
free(patchPath);
|
||||
if(!iboot) {
|
||||
add_hfs(ramdiskVolume, getFileFromOutputState(&ipswContents, ((StringValue*)getValueByKey(ibootDict, "File"))->value), "/ipwner/iboot.img2");
|
||||
StringValue* patchValue = (StringValue*) getValueByKey(ibootDict, "Patch");
|
||||
char* patchPath = (char*) malloc(sizeof(char) * (strlen(bundlePath) + strlen(patchValue->value) + 2));
|
||||
strcpy(patchPath, bundlePath);
|
||||
strcat(patchPath, "/");
|
||||
strcat(patchPath, patchValue->value);
|
||||
printf("patching /ipwner/iboot.img2 (%s)... ", patchPath);
|
||||
doPatchInPlace(ramdiskVolume, "/ipwner/iboot.img2", patchPath);
|
||||
free(patchPath);
|
||||
} else {
|
||||
cout << "adding custom iboot" << endl;
|
||||
add_hfs(ramdiskVolume, iboot, "/ipwner/iboot.img2");
|
||||
}
|
||||
|
||||
if(applelogo || recoverymode) {
|
||||
cout << " ... Adding boot logos" << endl;
|
||||
|
|
Загрузка…
Ссылка в новой задаче