VISO: Overhaul El Torito boot code insertion, now following the 7-Zip syntax which allows for explicit type definition
This commit is contained in:
@@ -106,13 +106,13 @@ typedef struct _viso_entry_ {
|
|||||||
} viso_entry_t;
|
} viso_entry_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint64_t vol_size_offsets[2], pt_meta_offsets[2], eltorito_offset;
|
uint64_t vol_size_offsets[2], pt_meta_offsets[2];
|
||||||
int format;
|
int format;
|
||||||
size_t metadata_sectors, all_sectors, entry_map_size, sector_size, file_fifo_pos;
|
size_t metadata_sectors, all_sectors, entry_map_size, sector_size, file_fifo_pos;
|
||||||
uint8_t *metadata;
|
uint8_t *metadata;
|
||||||
|
|
||||||
track_file_t tf;
|
track_file_t tf;
|
||||||
viso_entry_t *root_dir, *eltorito_entry, **entry_map, *file_fifo[VISO_OPEN_FILES];
|
viso_entry_t *root_dir, **entry_map, *file_fifo[VISO_OPEN_FILES];
|
||||||
} viso_t;
|
} viso_t;
|
||||||
|
|
||||||
static const char rr_eid[] = "RRIP_1991A"; /* identifiers used in ER field for Rock Ridge */
|
static const char rr_eid[] = "RRIP_1991A"; /* identifiers used in ER field for Rock Ridge */
|
||||||
@@ -745,10 +745,12 @@ viso_init(const char *dirname, int *error)
|
|||||||
|
|
||||||
/* Set up directory traversal. */
|
/* Set up directory traversal. */
|
||||||
cdrom_image_viso_log("VISO: Traversing directories:\n");
|
cdrom_image_viso_log("VISO: Traversing directories:\n");
|
||||||
viso_entry_t *entry, *last_entry, *dir, *last_dir;
|
viso_entry_t *entry, *last_entry, *dir, *last_dir, *eltorito_dir = NULL, *eltorito_entry = NULL;
|
||||||
struct dirent *readdir_entry;
|
struct dirent *readdir_entry;
|
||||||
int len;
|
int len, eltorito_others_present = 0;
|
||||||
size_t dir_path_len;
|
size_t dir_path_len;
|
||||||
|
uint64_t eltorito_offset = 0;
|
||||||
|
uint8_t eltorito_type = 0;
|
||||||
|
|
||||||
/* Fill root directory entry. */
|
/* Fill root directory entry. */
|
||||||
dir_path_len = strlen(dirname);
|
dir_path_len = strlen(dirname);
|
||||||
@@ -840,7 +842,7 @@ viso_init(const char *dirname, int *error)
|
|||||||
memset(&entry->stats, 0x00, sizeof(struct stat));
|
memset(&entry->stats, 0x00, sizeof(struct stat));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Handle file size. */
|
/* Handle file size and El Torito boot code. */
|
||||||
if (!S_ISDIR(entry->stats.st_mode)) {
|
if (!S_ISDIR(entry->stats.st_mode)) {
|
||||||
/* Limit to 4 GB - 1 byte. */
|
/* Limit to 4 GB - 1 byte. */
|
||||||
if (entry->stats.st_size > ((uint32_t) -1))
|
if (entry->stats.st_size > ((uint32_t) -1))
|
||||||
@@ -850,11 +852,36 @@ viso_init(const char *dirname, int *error)
|
|||||||
viso->entry_map_size += entry->stats.st_size / viso->sector_size;
|
viso->entry_map_size += entry->stats.st_size / viso->sector_size;
|
||||||
if (entry->stats.st_size % viso->sector_size)
|
if (entry->stats.st_size % viso->sector_size)
|
||||||
viso->entry_map_size++; /* round up to the next sector */
|
viso->entry_map_size++; /* round up to the next sector */
|
||||||
}
|
|
||||||
|
|
||||||
/* Detect El Torito boot code file and set it accordingly. */
|
/* Detect El Torito boot code file and set it accordingly. */
|
||||||
if ((dir == viso->root_dir) && !strnicmp(readdir_entry->d_name, "eltorito.", 9) && (!stricmp(readdir_entry->d_name + 9, "com") || !stricmp(readdir_entry->d_name + 9, "img")))
|
if (dir == eltorito_dir) {
|
||||||
viso->eltorito_entry = entry;
|
if (!stricmp(readdir_entry->d_name, "Boot-NoEmul.img")) {
|
||||||
|
eltorito_type = 0x00;
|
||||||
|
have_eltorito_entry:
|
||||||
|
if (eltorito_entry)
|
||||||
|
eltorito_others_present = 1; /* flag that the boot code directory contains other files */
|
||||||
|
eltorito_entry = entry;
|
||||||
|
} else if (!stricmp(readdir_entry->d_name, "Boot-1.2M.img")) {
|
||||||
|
eltorito_type = 0x01;
|
||||||
|
goto have_eltorito_entry;
|
||||||
|
} else if (!stricmp(readdir_entry->d_name, "Boot-1.44M.img")) {
|
||||||
|
eltorito_type = 0x02;
|
||||||
|
goto have_eltorito_entry;
|
||||||
|
} else if (!stricmp(readdir_entry->d_name, "Boot-2.88M.img")) {
|
||||||
|
eltorito_type = 0x03;
|
||||||
|
goto have_eltorito_entry;
|
||||||
|
} else if (!stricmp(readdir_entry->d_name, "Boot-HardDisk.img")) {
|
||||||
|
eltorito_type = 0x04;
|
||||||
|
goto have_eltorito_entry;
|
||||||
|
} else {
|
||||||
|
eltorito_others_present = 1; /* flag that the boot code directory contains other files */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if ((dir == viso->root_dir) && !stricmp(readdir_entry->d_name, "[BOOT]")) {
|
||||||
|
/* Set this as the directory containing El Torito boot code. */
|
||||||
|
eltorito_dir = entry;
|
||||||
|
eltorito_others_present = 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Set short filename. */
|
/* Set short filename. */
|
||||||
if (viso_fill_fn_short(entry->name_short, entry, dir_entries)) {
|
if (viso_fill_fn_short(entry->name_short, entry, dir_entries)) {
|
||||||
@@ -1008,8 +1035,8 @@ next_dir:
|
|||||||
|
|
||||||
/* Write El Torito boot descriptor. This is an awkward spot for
|
/* Write El Torito boot descriptor. This is an awkward spot for
|
||||||
that, but the spec requires it to be the second descriptor. */
|
that, but the spec requires it to be the second descriptor. */
|
||||||
if (!i && viso->eltorito_entry) {
|
if (!i && eltorito_entry) {
|
||||||
cdrom_image_viso_log("VISO: Writing El Torito boot descriptor for entry [%08X]\n", viso->eltorito_entry);
|
cdrom_image_viso_log("VISO: Writing El Torito boot descriptor for entry [%08X]\n", eltorito_entry);
|
||||||
|
|
||||||
p = data;
|
p = data;
|
||||||
if (viso->format <= VISO_FORMAT_HSF)
|
if (viso->format <= VISO_FORMAT_HSF)
|
||||||
@@ -1024,7 +1051,7 @@ next_dir:
|
|||||||
VISO_SKIP(p, 40);
|
VISO_SKIP(p, 40);
|
||||||
|
|
||||||
/* Save the boot catalog pointer's offset for later. */
|
/* Save the boot catalog pointer's offset for later. */
|
||||||
viso->eltorito_offset = ftello64(viso->tf.file) + (p - data);
|
eltorito_offset = ftello64(viso->tf.file) + (p - data);
|
||||||
|
|
||||||
/* Blank the rest of the working sector. */
|
/* Blank the rest of the working sector. */
|
||||||
memset(p, 0x00, viso->sector_size - (p - data));
|
memset(p, 0x00, viso->sector_size - (p - data));
|
||||||
@@ -1059,10 +1086,10 @@ next_dir:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Handle El Torito boot catalog. */
|
/* Handle El Torito boot catalog. */
|
||||||
if (viso->eltorito_entry) {
|
if (eltorito_entry) {
|
||||||
/* Write a pointer to this boot catalog to the boot descriptor. */
|
/* Write a pointer to this boot catalog to the boot descriptor. */
|
||||||
*((uint32_t *) data) = cpu_to_le32(ftello64(viso->tf.file) / viso->sector_size);
|
*((uint32_t *) data) = cpu_to_le32(ftello64(viso->tf.file) / viso->sector_size);
|
||||||
viso_pwrite(data, viso->eltorito_offset, 4, 1, viso->tf.file);
|
viso_pwrite(data, eltorito_offset, 4, 1, viso->tf.file);
|
||||||
|
|
||||||
/* Fill boot catalog validation entry. */
|
/* Fill boot catalog validation entry. */
|
||||||
p = data;
|
p = data;
|
||||||
@@ -1085,38 +1112,14 @@ next_dir:
|
|||||||
|
|
||||||
/* Now fill the default boot entry. */
|
/* Now fill the default boot entry. */
|
||||||
*p++ = 0x88; /* bootable flag */
|
*p++ = 0x88; /* bootable flag */
|
||||||
|
*p++ = eltorito_type; /* boot media type */
|
||||||
if (viso->eltorito_entry->name_short[9] == 'C') { /* boot media type: non-emulation */
|
|
||||||
*p++ = 0x00;
|
|
||||||
} else { /* boot media type: emulation */
|
|
||||||
/* This could use with a decoupling of fdd_img's algorithms
|
|
||||||
for loading non-raw images and detecting raw image sizes. */
|
|
||||||
switch (viso->eltorito_entry->stats.st_size) {
|
|
||||||
case 0 ... 1228800: /* 1.2 MB */
|
|
||||||
*p++ = 0x01;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 1228801 ... 1474560: /* 1.44 MB */
|
|
||||||
*p++ = 0x02;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 1474561 ... 2949120: /* 2.88 MB */
|
|
||||||
*p++ = 0x03;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default: /* hard drive */
|
|
||||||
*p++ = 0x04;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
*p++ = 0x00; /* load segment */
|
*p++ = 0x00; /* load segment */
|
||||||
*p++ = 0x00;
|
*p++ = 0x00;
|
||||||
*p++ = 0x00; /* system type (is this even relevant?) */
|
*p++ = 0x00; /* system type (is this even relevant?) */
|
||||||
*p++ = 0x00; /* reserved */
|
*p++ = 0x00; /* reserved */
|
||||||
|
|
||||||
/* Save offsets to the boot catalog entry's offset and size fields for later. */
|
/* Save offsets to the boot catalog entry's offset and size fields for later. */
|
||||||
viso->eltorito_offset = ftello64(viso->tf.file) + (p - data);
|
eltorito_offset = ftello64(viso->tf.file) + (p - data);
|
||||||
|
|
||||||
/* Blank the rest of the working sector. This includes the sector count,
|
/* Blank the rest of the working sector. This includes the sector count,
|
||||||
ISO sector offset and 20-byte selection criteria fields at the end. */
|
ISO sector offset and 20-byte selection criteria fields at the end. */
|
||||||
@@ -1132,6 +1135,10 @@ next_dir:
|
|||||||
memset(data, 0x00, write);
|
memset(data, 0x00, write);
|
||||||
fwrite(data, write, 1, viso->tf.file);
|
fwrite(data, write, 1, viso->tf.file);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Flag that we shouldn't hide the boot code directory if it contains other files. */
|
||||||
|
if (eltorito_others_present)
|
||||||
|
eltorito_dir = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Write each path table. */
|
/* Write each path table. */
|
||||||
@@ -1150,8 +1157,9 @@ next_dir:
|
|||||||
dir = viso->root_dir;
|
dir = viso->root_dir;
|
||||||
uint16_t pt_idx = 1;
|
uint16_t pt_idx = 1;
|
||||||
while (dir) {
|
while (dir) {
|
||||||
/* Ignore . and .. pseudo-directories. */
|
/* Ignore . and .. pseudo-directories, and hide the El Torito
|
||||||
if (dir->name_short[0] == '.' && (dir->name_short[1] == '\0' || (dir->name_short[1] == '.' && dir->name_short[2] == '\0'))) {
|
boot code directory if no other files are present in it. */
|
||||||
|
if ((dir->name_short[0] == '.' && (dir->name_short[1] == '\0' || (dir->name_short[1] == '.' && dir->name_short[2] == '\0'))) || (dir == eltorito_dir)) {
|
||||||
dir = dir->next_dir;
|
dir = dir->next_dir;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -1228,6 +1236,12 @@ next_dir:
|
|||||||
/* Go through directories. */
|
/* Go through directories. */
|
||||||
dir = viso->root_dir;
|
dir = viso->root_dir;
|
||||||
while (dir) {
|
while (dir) {
|
||||||
|
/* Hide the El Torito boot code directory if no other files are present in it. */
|
||||||
|
if (dir == eltorito_dir) {
|
||||||
|
dir = dir->next_dir;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
/* Pad to the next sector if required. */
|
/* Pad to the next sector if required. */
|
||||||
write = ftello64(viso->tf.file) % viso->sector_size;
|
write = ftello64(viso->tf.file) % viso->sector_size;
|
||||||
if (write) {
|
if (write) {
|
||||||
@@ -1255,8 +1269,9 @@ next_dir:
|
|||||||
/* Go through entries in this directory. */
|
/* Go through entries in this directory. */
|
||||||
entry = dir->first_child;
|
entry = dir->first_child;
|
||||||
while (entry) {
|
while (entry) {
|
||||||
/* Skip the El Torito boot code entry if present. */
|
/* Skip the El Torito boot code entry if present, or hide the
|
||||||
if (entry == viso->eltorito_entry)
|
boot code directory if no other files are present in it. */
|
||||||
|
if ((entry == eltorito_entry) || (entry == eltorito_dir))
|
||||||
goto next_entry;
|
goto next_entry;
|
||||||
|
|
||||||
cdrom_image_viso_log("[%08X] %s => %s\n", entry, dir->path,
|
cdrom_image_viso_log("[%08X] %s => %s\n", entry, dir->path,
|
||||||
@@ -1386,10 +1401,10 @@ next_entry:
|
|||||||
/* Write this file's base sector offset to its directory
|
/* Write this file's base sector offset to its directory
|
||||||
entries, unless this is the El Torito boot code entry,
|
entries, unless this is the El Torito boot code entry,
|
||||||
in which case, write offset and size to the boot entry. */
|
in which case, write offset and size to the boot entry. */
|
||||||
if (entry == viso->eltorito_entry) {
|
if (entry == eltorito_entry) {
|
||||||
/* Load the entire file if not emulating, or just the first virtual
|
/* Load the entire file if not emulating, or just the first virtual
|
||||||
sector (which usually contains all the boot code) if emulating. */
|
sector (which usually contains all the boot code) if emulating. */
|
||||||
if (entry->name_short[9] == 'C') { /* non-emulation */
|
if (eltorito_type == 0x00) { /* non-emulation */
|
||||||
uint32_t boot_size = entry->stats.st_size;
|
uint32_t boot_size = entry->stats.st_size;
|
||||||
if (boot_size % 512) /* round up */
|
if (boot_size % 512) /* round up */
|
||||||
boot_size += 512 - (boot_size % 512);
|
boot_size += 512 - (boot_size % 512);
|
||||||
@@ -1398,7 +1413,7 @@ next_entry:
|
|||||||
*((uint16_t *) &data[0]) = cpu_to_le16(1);
|
*((uint16_t *) &data[0]) = cpu_to_le16(1);
|
||||||
}
|
}
|
||||||
*((uint32_t *) &data[2]) = cpu_to_le32(viso->all_sectors * base_factor);
|
*((uint32_t *) &data[2]) = cpu_to_le32(viso->all_sectors * base_factor);
|
||||||
viso_pwrite(data, viso->eltorito_offset, 6, 1, viso->tf.file);
|
viso_pwrite(data, eltorito_offset, 6, 1, viso->tf.file);
|
||||||
} else {
|
} else {
|
||||||
p = data;
|
p = data;
|
||||||
VISO_LBE_32(p, viso->all_sectors * base_factor);
|
VISO_LBE_32(p, viso->all_sectors * base_factor);
|
||||||
|
Reference in New Issue
Block a user