+ if (cdbuffer == NULL) {
+ cdbuffer = malloc(sizeof(*cdbuffer));
+ if (cdbuffer == NULL) {
+ err("OOM\n");
+ return -1;
+ }
+ }
+ if (pBZ2_bzBuffToBuffDecompress == NULL) {
+ void *h = dlopen("/usr/lib/libbz2.so.1", RTLD_LAZY);
+ if (h == NULL)
+ h = dlopen("./lib/libbz2.so.1", RTLD_LAZY);
+ if (h != NULL) {
+ pBZ2_bzBuffToBuffDecompress = dlsym(h, "BZ2_bzBuffToBuffDecompress");
+ if (pBZ2_bzBuffToBuffDecompress == NULL) {
+ err("dlsym bz2: %s", dlerror());
+ dlclose(h);
+ }
+ }
+ }
+ return 0;
+}
+
+static long handle_eboot(void)
+{
+ struct {
+ unsigned int sig;
+ unsigned int dontcare[8];
+ unsigned int psar_offs;
+ } pbp_hdr;
+ struct {
+ unsigned int offset;
+ unsigned int size;
+ unsigned int dontcare[6];
+ } index_entry;
+ char psar_sig[9];
+ unsigned int cdimg_base;
+ int i, ret;
+ FILE *f;
+
+ f = fopen(cd_fname, "rb");
+ if (f == NULL) {
+ err("missing file: %s: ", cd_fname);
+ perror(NULL);
+ return -1;
+ }
+
+ ret = fread(&pbp_hdr, 1, sizeof(pbp_hdr), f);
+ if (ret != sizeof(pbp_hdr)) {
+ err("failed to read pbp\n");
+ goto fail_io;
+ }
+
+ ret = fseek(f, pbp_hdr.psar_offs, SEEK_SET);
+ if (ret != 0) {
+ err("failed to seek to %x\n", pbp_hdr.psar_offs);
+ goto fail_io;
+ }
+
+ ret = fread(psar_sig, 1, sizeof(psar_sig), f);
+ if (ret != sizeof(psar_sig)) {
+ err("failed to read psar_sig\n");
+ goto fail_io;
+ }
+
+ psar_sig[8] = 0;
+ if (strcmp(psar_sig, "PSISOIMG") != 0) {
+ err("bad psar_sig: %s\n", psar_sig);
+ goto fail_io;
+ }
+
+ // seek to ISO index
+ ret = fseek(f, 0x4000 - sizeof(psar_sig), SEEK_CUR);
+ if (ret != 0) {
+ err("failed to seek to ISO index\n");
+ goto fail_io;
+ }
+
+ cd_index_len = (0x100000 - 0x4000) / sizeof(index_entry);
+ cd_index_table = malloc((cd_index_len + 1) * sizeof(cd_index_table[0]));
+ if (cd_index_table == NULL)
+ goto fail_io;
+
+ cdimg_base = pbp_hdr.psar_offs + 0x100000;
+ for (i = 0; i < cd_index_len; i++) {
+ ret = fread(&index_entry, 1, sizeof(index_entry), f);
+ if (ret != sizeof(index_entry)) {
+ err("failed to read index_entry #%d\n", i);
+ goto fail_index;
+ }
+
+ if (index_entry.size == 0)
+ break;
+
+ cd_index_table[i] = cdimg_base + index_entry.offset;
+ }
+ cd_index_table[i] = cdimg_base + index_entry.offset + index_entry.size;
+
+ cd_compression = CDRC_ZLIB2;
+ cd_sectors_per_blk = 16;
+ cd_file = f;
+
+ printf(PFX "Loaded EBOOT CD Image: %s.\n", cd_fname);
+ return 0;
+
+fail_index:
+ free(cd_index_table);
+ cd_index_table = NULL;
+fail_io:
+ fclose(f);
+ return -1;