16#define IMAGE_COMMENT_BASESIZE 31
27 unsigned int FileOffset;
28 unsigned int ExtInfoOffset;
31 unsigned short int ExtInfoEntrySize;
44 DPRINTF(
"Found 'EXTINFO' at 0x%x\n", offset);
45 fd->ExtInfoOffset = offset;
66 if (GetRomDirExtInfoOffset(ImageStat, fd) == 0) {
67 unsigned int offset = 0;
70 fd->FileOffset = offset;
72 fd->ExtInfoEntrySize =
RomDirEntry->ExtInfoEntrySize;
87static int GetExtInfoStat(
const struct ROMImgStat *ImageStat,
struct RomDirFileFd *fd,
unsigned char type,
void **buffer,
unsigned int nbytes)
90 unsigned int offset, BytesToCopy;
94 while (offset < fd->ExtInfoEntrySize) {
97 if (ExtInfoEntry->type == EXTINFO_FIELD_TYPE_DATE || ExtInfoEntry->type == EXTINFO_FIELD_TYPE_COMMENT) {
98 if (type == ExtInfoEntry->type) {
99 if (nbytes >= ExtInfoEntry->ExtLength) {
100 BytesToCopy = ExtInfoEntry->ExtLength;
103 if (*buffer != NULL) {
104 BytesToCopy = nbytes;
106 *buffer = malloc(ExtInfoEntry->ExtLength);
107 BytesToCopy = ExtInfoEntry->ExtLength;
109 result = ExtInfoEntry->ExtLength;
112 memcpy(*buffer, &((
const unsigned char *)ImageStat->image)[fd->ExtInfoOffset + offset +
sizeof(
struct ExtInfoFieldEntry)], BytesToCopy);
117 }
else if (ExtInfoEntry->type == EXTINFO_FIELD_TYPE_VERSION) {
118 if (type == ExtInfoEntry->type) {
119 if (nbytes >=
sizeof(ExtInfoEntry->value)) {
121 memcpy(buffer, &ExtInfoEntry->value,
sizeof(ExtInfoEntry->value));
130 }
else if (ExtInfoEntry->type == EXTINFO_FIELD_TYPE_NULL) {
134 ERROR(
"Unknown EXTINFO entry type: 0x%02x @ ROM offset: 0x%x, EXTINFO offset: %u\n", ExtInfoEntry->type, fd->ExtInfoOffset + offset, offset);
143int CreateBlankROMImg(
const char *filename,
ROMIMG *ROMImg)
145 unsigned int CommentLength;
146 char LocalhostName[32] = {0}, cwd[PATH_MAX] = {0}, UserName[32] = {0};
150 memset(ROMImg, 0,
sizeof(
ROMIMG));
152 ROMImg->date = GetSystemDate();
153#if defined(_WIN32) || defined(WIN32)
154 GetUsername(UserName,
sizeof(UserName));
156 getlogin_r(UserName,
sizeof(UserName));
158 GetLocalhostName(LocalhostName,
sizeof(LocalhostName));
159 GetCurrentWorkingDirectory(cwd,
sizeof(cwd));
161 CommentLength = IMAGE_COMMENT_BASESIZE + strlen(filename) +
sizeof(LocalhostName) +
sizeof(UserName) +
sizeof(cwd);
162 ROMImg->comment = (
char *)malloc( CommentLength+1);
163 if (!ROMImg->comment)
return ENOMEM;
164 snprintf(ROMImg->comment, CommentLength,
"%08x,conffile,%s,%s@%s/%s", ROMImg->date, filename, UserName, LocalhostName, cwd);
167 ROMImg->NumFiles = 1;
170 memset(ResetFile->RomDir.name, 0,
sizeof(ResetFile->RomDir.name));
171 strcpy(ResetFile->RomDir.name,
"RESET");
172 ResetFile->RomDir.ExtInfoEntrySize =
sizeof(ROMImg->date) +
sizeof(
struct ExtInfoFieldEntry);
173 ResetFile->RomDir.size = 0;
174 ResetFile->FileData = NULL;
175 ResetFile->ExtInfoData = (
unsigned char *)malloc(ResetFile->RomDir.ExtInfoEntrySize);
177 ExtInfoEntry->value = 0;
178 ExtInfoEntry->ExtLength =
sizeof(ROMImg->date);
179 ExtInfoEntry->type = EXTINFO_FIELD_TYPE_DATE;
180 memcpy((
void *)((RMIMG_PTRCAST)ResetFile->ExtInfoData +
sizeof(
struct ExtInfoFieldEntry)), &ROMImg->date, ExtInfoEntry->ExtLength);
185int WriteROMImg(
const char *file,
const ROMIMG *ROMImg)
188 unsigned char *extinfo;
189 struct RomDirEntry ROMDIR_romdir, EXTINFO_romdir, NULL_romdir;
190 unsigned int i, TotalExtInfoSize, ExtInfoOffset, CommentLengthRounded;
194 CommentLengthRounded = (strlen(ROMImg->comment) + 1 + 3) & ~3;
196 for (i = 0, TotalExtInfoSize = 0; i < ROMImg->NumFiles; i++) {
197 TotalExtInfoSize += ROMImg->files[i].RomDir.ExtInfoEntrySize;
198 if (ROMImg->files[i].RomDir.ExtInfoEntrySize % 4 != 0) {
199 WARNING(
"ASSERT ROMImg->files[%u].RomDir.ExtInfoEntrySize%%4==0\n", i);
204 if ((extinfo = (
unsigned char *)malloc(TotalExtInfoSize)) != NULL) {
205 memset(&NULL_romdir, 0,
sizeof(NULL_romdir));
206 memset(&ROMDIR_romdir, 0,
sizeof(ROMDIR_romdir));
207 memset(&EXTINFO_romdir, 0,
sizeof(EXTINFO_romdir));
210 memcpy(&extinfo[ExtInfoOffset], ROMImg->files[0].ExtInfoData, ROMImg->files[0].RomDir.ExtInfoEntrySize);
211 ExtInfoOffset += ROMImg->files[0].RomDir.ExtInfoEntrySize;
214 strcpy(ROMDIR_romdir.name,
"ROMDIR");
215 ROMDIR_romdir.size = (ROMImg->NumFiles + 3) *
sizeof(
struct RomDirEntry);
216 ROMDIR_romdir.ExtInfoEntrySize =
sizeof(
struct ExtInfoFieldEntry) + CommentLengthRounded;
218 ExtInfoEntry->value = 0;
219 ExtInfoEntry->ExtLength = CommentLengthRounded;
220 ExtInfoEntry->type = EXTINFO_FIELD_TYPE_COMMENT;
221 memcpy(&extinfo[ExtInfoOffset +
sizeof(
struct ExtInfoFieldEntry)], ROMImg->comment, ExtInfoEntry->ExtLength);
224 strcpy(EXTINFO_romdir.name,
"EXTINFO");
225 EXTINFO_romdir.size = TotalExtInfoSize;
226 EXTINFO_romdir.ExtInfoEntrySize = 0;
228 for (i = 1; i < ROMImg->NumFiles; i++) {
229 if (ExtInfoOffset % 4 != 0) {
230 WARNING(
"ASSERT: ExtInfoOffset[%u]%%4==0: %u\n", i, ExtInfoOffset);
233 memcpy(&extinfo[ExtInfoOffset], ROMImg->files[i].ExtInfoData, ROMImg->files[i].RomDir.ExtInfoEntrySize);
234 ExtInfoOffset += ROMImg->files[i].RomDir.ExtInfoEntrySize;
238 if ((OutputFile = fopen(file,
"wb")) != NULL) {
241 fwrite(ROMImg->files[0].FileData, 1, ROMImg->files[0].RomDir.size, OutputFile);
244 fwrite(&ROMImg->files[0].RomDir,
sizeof(
struct RomDirEntry), 1, OutputFile);
245 fwrite(&ROMDIR_romdir,
sizeof(
struct RomDirEntry), 1, OutputFile);
246 fwrite(&EXTINFO_romdir,
sizeof(
struct RomDirEntry), 1, OutputFile);
247 for (i = 1; i < ROMImg->NumFiles; i++) {
248 fwrite(&ROMImg->files[i].RomDir,
sizeof(
struct RomDirEntry), 1, OutputFile);
250 fwrite(&NULL_romdir,
sizeof(
struct RomDirEntry), 1, OutputFile);
253 fwrite(extinfo, 1, TotalExtInfoSize, OutputFile);
254 if ((FileAlignMargin = (ftell(OutputFile) % 16)) > 0)
255 fseek(OutputFile, 16 - FileAlignMargin, SEEK_CUR);
258 for (i = 1; i < ROMImg->NumFiles; i++) {
259 fwrite(ROMImg->files[i].FileData, 1, ROMImg->files[i].RomDir.size, OutputFile);
260 if ((FileAlignMargin = (ftell(OutputFile) % 16)) > 0)
261 fseek(OutputFile, 16 - FileAlignMargin, SEEK_CUR);
275int LoadROMImg(
ROMIMG *ROMImg,
const char *path)
279 unsigned int ExtInfoOffset, DataStartOffset, ScanLimit;
284 memset(ROMImg, 0,
sizeof(
ROMIMG));
286 if ((InputFile = fopen(path,
"rb")) != NULL) {
287 fseek(InputFile, 0, SEEK_END);
288 ImageStat.size = ftell(InputFile);
291 if ((ImageStat.image = malloc(ImageStat.size)) != NULL) {
292 if (fread(ImageStat.image, 1, ImageStat.size, InputFile) == ImageStat.size) {
297 for (i = 0, result = -
EIO, ScanLimit = 0x40000 < ImageStat.size ? 0x40000 : ImageStat.size; i < ScanLimit; i++) {
299 if (((
const char *)ImageStat.image)[i] ==
'R' &&
300 ((
const char *)ImageStat.image)[i + 1] ==
'E' &&
301 ((
const char *)ImageStat.image)[i + 2] ==
'S' &&
302 ((
const char *)ImageStat.image)[i + 3] ==
'E' &&
303 ((
const char *)ImageStat.image)[i + 4] ==
'T') {
310 ImageStat.ROMFS_start = (
void *)((RMIMG_PTRCAST)ImageStat.image + DataStartOffset);
311 if (OpenRomDirFile(&ImageStat,
"RESET", &
RomDirFileFd) != 0) {
312 ERROR(
" Unable to locate RESET!\n");
313 free(ImageStat.image);
318 ERROR(
" Size of RESET does not match the start of ROMFS!\n");
319 free(ImageStat.image);
324 GetExtInfoStat(&ImageStat, &
RomDirFileFd, EXTINFO_FIELD_TYPE_DATE, &ptr,
sizeof(ROMImg->date));
326 if (OpenRomDirFile(&ImageStat,
"ROMDIR", &
RomDirFileFd) != 0) {
327 ERROR(
" Unable to locate ROMDIR!\n");
328 free(ImageStat.image);
333 ROMImg->comment = NULL;
334 GetExtInfoStat(&ImageStat, &
RomDirFileFd, EXTINFO_FIELD_TYPE_COMMENT, (
void **)&ROMImg->comment, 0);
337 unsigned int offset = 0;
340 while (RomDir->name[0] !=
'\0') {
341 if (strncmp(RomDir->name,
"ROMDIR",
sizeof(RomDir->name)) != 0 && strncmp(RomDir->name,
"EXTINFO",
sizeof(RomDir->name)) != 0) {
344 ROMImg->files = (ROMImg->files == NULL) ? (
struct FileEntry *)malloc(
sizeof(
struct FileEntry)) : (struct
FileEntry *)realloc(ROMImg->files, ROMImg->NumFiles * sizeof(struct
FileEntry));
345 file = &ROMImg->files[ROMImg->NumFiles - 1];
347 memcpy(&file->RomDir, RomDir,
sizeof(
struct RomDirEntry));
348 file->ExtInfoData = (
unsigned char *)malloc(RomDir->ExtInfoEntrySize);
349 memcpy(file->ExtInfoData, (
void *)((RMIMG_PTRCAST)ImageStat.image +
RomDirFileFd.ExtInfoOffset + ExtInfoOffset), RomDir->ExtInfoEntrySize);
350 file->FileData = malloc(RomDir->size);
351 memcpy(file->FileData, (
void *)((RMIMG_PTRCAST)ImageStat.image + offset), RomDir->size);
354 offset += (RomDir->size + 0xF) & ~0xF;
355 ExtInfoOffset += RomDir->ExtInfoEntrySize;
359 WARNING(
"Could not locate RESET file, aborting...\n");
363 ERROR(
"failed to read %u bytes\n", ImageStat.size);
367 free(ImageStat.image);
369 ERROR(
"failed to malloc %u bytes\n", ImageStat.size);
375 ERROR(
"cant open '%s'\n", path);
382void UnloadROMImg(
ROMIMG *ROMImg)
384 DPRINTF(
"start...\n");
386 if (ROMImg->comment != NULL) {
387 free(ROMImg->comment);
389 if (ROMImg->files != NULL) {
391 for (i = 0; i < ROMImg->NumFiles; i++) {
392 if (ROMImg->files[i].ExtInfoData != NULL)
393 free(ROMImg->files[i].ExtInfoData);
394 if (ROMImg->files[i].FileData != NULL)
395 free(ROMImg->files[i].FileData);
401 memset(ROMImg, 0,
sizeof(
ROMIMG));
404static void *ReallocExtInfoArea(
struct FileEntry *file,
unsigned short int nbytes)
406 return (file->ExtInfoData = (file->ExtInfoData == NULL) ? (
unsigned char *)malloc(nbytes +
sizeof(
struct ExtInfoFieldEntry)) : (unsigned char *)realloc(file->ExtInfoData, file->RomDir.ExtInfoEntrySize + nbytes + sizeof(struct
ExtInfoFieldEntry)));
409static int AddExtInfoStat(
struct FileEntry *file,
unsigned char type,
void *data,
unsigned char nbytes)
414 case EXTINFO_FIELD_TYPE_DATE:
415 case EXTINFO_FIELD_TYPE_COMMENT:
416 if (type != EXTINFO_FIELD_TYPE_DATE || (type == EXTINFO_FIELD_TYPE_DATE && nbytes == 4)) {
417 if (ReallocExtInfoArea(file, nbytes) != NULL) {
418 ExtInfo = (
struct ExtInfoFieldEntry *)(file->ExtInfoData + file->RomDir.ExtInfoEntrySize);
420 ExtInfo->ExtLength = (nbytes + 0x3) & ~0x3;
421 ExtInfo->type = type;
422 memcpy(file->ExtInfoData + file->RomDir.ExtInfoEntrySize +
sizeof(
struct ExtInfoFieldEntry), data, nbytes);
424 file->RomDir.ExtInfoEntrySize += ExtInfo->ExtLength +
sizeof(
struct ExtInfoFieldEntry);
432 case EXTINFO_FIELD_TYPE_VERSION:
434 if (ReallocExtInfoArea(file, 0) != NULL) {
435 ExtInfo = (
struct ExtInfoFieldEntry *)(file->ExtInfoData + file->RomDir.ExtInfoEntrySize);
436 ExtInfo->value = *(
unsigned short int *)data;
437 ExtInfo->ExtLength = 0;
438 ExtInfo->type = type;
455int AddFile(
ROMIMG *ROMImg,
const char *path,
int upperconv)
460 unsigned int FileDateStamp;
461 unsigned short FileVersion;
462 if ((InputFile = fopen(path,
"rb")) != NULL) {
463 const char* fname = strrchr(path, PATHSEP);
464 if (fname == NULL) fname = path;
else fname++;
466 strncpy(tbuf, fname,
sizeof(tbuf));
467 tbuf[
sizeof(tbuf) - 1] =
'\0';
468 if (tbuf[0] !=
'\0') {
471 char* T = strrchr(fname,
'.');
472 if (T != NULL) *T =
'\0';
476 fseek(InputFile, 0, SEEK_END);
477 size = ftell(InputFile);
482 if (strcmp(fname,
"RESET")) {
483 if (!IsFileExists(ROMImg, fname)) {
486 if ((ROMImg->files = (ROMImg->files == NULL) ? (
struct FileEntry *)malloc(
sizeof(
struct FileEntry)) : (struct
FileEntry *)realloc(ROMImg->files, ROMImg->NumFiles * sizeof(struct
FileEntry))) != NULL) {
487 file = &ROMImg->files[ROMImg->NumFiles - 1];
488 memset(&ROMImg->files[ROMImg->NumFiles - 1], 0,
sizeof(
struct FileEntry));
490 strncpy(file->RomDir.name, fname,
sizeof(file->RomDir.name));
491 file->RomDir.name[
sizeof(file->RomDir.name) - 1] =
'\0';
492 file->RomDir.ExtInfoEntrySize = 0;
494 FileDateStamp = GetFileCreationDate(path);
495 AddExtInfoStat(&ROMImg->files[ROMImg->NumFiles - 1], EXTINFO_FIELD_TYPE_DATE, &FileDateStamp, 4);
497 if (IsSonyRXModule(path)) {
498 char ModuleDescription[32];
499 if ((result = GetSonyRXModInfo(path, ModuleDescription,
sizeof(ModuleDescription), &FileVersion)) == 0) {
500 AddExtInfoStat(&ROMImg->files[ROMImg->NumFiles - 1], EXTINFO_FIELD_TYPE_VERSION, &FileVersion, 2);
501 AddExtInfoStat(&ROMImg->files[ROMImg->NumFiles - 1], EXTINFO_FIELD_TYPE_COMMENT, ModuleDescription, strlen(ModuleDescription) + 1);
507 file->RomDir.size = size;
508 file->FileData = malloc(size);
509 if (fread(file->FileData, 1, size, InputFile) != size) {
510 ERROR(
"failed to read %d bytes\n", size);
519 if (ROMImg->files[0].RomDir.size < 1) {
520 file = &ROMImg->files[0];
521 file->RomDir.size = size;
522 file->FileData = malloc(size);
523 if (fread(file->FileData, 1, size, InputFile) != file->RomDir.size) {
524 ERROR(
"failed to read %u bytes\n", file->RomDir.size);
539int DeleteFile(
ROMIMG *ROMImg,
const char *filename)
545 if (strcmp(
"RESET", filename)) {
547 for (result =
ENOENT, i = 0, file = ROMImg->files; i < ROMImg->NumFiles; i++, file++) {
548 if (strncmp(file->RomDir.name, filename,
sizeof(file->RomDir.name)) == 0) {
549 if (file->FileData != NULL)
550 free(file->FileData);
552 if (file->ExtInfoData != NULL)
553 free(file->ExtInfoData);
554 for (; i < ROMImg->NumFiles; i++)
555 memcpy(&ROMImg->files[i], &ROMImg->files[i + 1],
sizeof(
struct FileEntry));
556 ROMImg->files = (
struct FileEntry *)realloc(ROMImg->files, (--ROMImg->NumFiles) *
sizeof(
struct FileEntry));
562 file = &ROMImg->files[0];
563 if (file->RomDir.size > 0) {
564 file->FileData = NULL;
565 file->RomDir.size = 0;
574int ExtractFile(
const ROMIMG *ROMImg,
const char *filename,
const char *FileToExtract)
581 for (result =
ENOENT, i = 0, file = ROMImg->files; i < ROMImg->NumFiles; i++, file++) {
582 if (strncmp(file->RomDir.name, FileToExtract,
sizeof(file->RomDir.name)) == 0) {
583 if ((OutputFile = fopen(filename,
"wb")) != NULL) {
584 result = (fwrite(file->FileData, 1, file->RomDir.size, OutputFile) == file->RomDir.size) ? 0 :
EIO;
595int IsFileExists(
const ROMIMG *ROMImg,
const char *filename)
601 for (result = 0, i = 0, file = ROMImg->files; i < ROMImg->NumFiles; i++, file++) {
602 if (strncmp(file->RomDir.name, filename,
sizeof(file->RomDir.name)) == 0) {