diff --git a/src/libcdio/cdio/iso9660.h b/src/libcdio/cdio/iso9660.h index 04308909..6812e040 100644 --- a/src/libcdio/cdio/iso9660.h +++ b/src/libcdio/cdio/iso9660.h @@ -162,6 +162,7 @@ extern enum iso_vd_enum_s { extern const char ISO_STANDARD_ID[sizeof("CD001")-1]; #define ISO_STANDARD_ID "CD001" +#define EL_TORITO_ID "EL TORITO SPECIFICATION\0\0\0\0\0\0\0\0\0" #define CDIO_EXTENT_BLOCKS(size) ((size + (ISO_BLOCKSIZE - 1)) / ISO_BLOCKSIZE) @@ -506,6 +507,37 @@ struct iso9660_svd_s { typedef struct iso9660_svd_s iso9660_svd_t; +/*! + \brief ISO-9660 Boot Record Volume Descriptor. + */ +struct iso9660_brvd_s { + uint8_t type; /**< ISO_VD_BOOT_RECORD - 0 */ + char id[5]; /**< ISO_STANDARD_ID "CD001" */ + uint8_t version; /**< value 1 for El Torito */ + char system_id[ISO_MAX_SYSTEM_ID]; /**< Boot system ID */ + uint8_t unused1[32]; /**< unused - value 0 */ + uint32_t boot_catalog_sector; /**< first sector of boot catalog */ + uint8_t unused2[1973]; /**< Unused - value 0 */ +} GNUC_PACKED; + +typedef struct iso9660_brvd_s iso9660_brvd_t; + +/*! + \brief ISO-9660 Boot Record Volume Descriptor. + */ +struct iso9660_br_s { + uint8_t boot_id; /**< Boot indicator - 0x88 */ + uint8_t media_type; /**< Boot media type - 0 for no emul. */ + uint16_t load_seg; /**< Load segment for x86 */ + uint8_t system_type; /**< System type - 0 for x86 */ + uint8_t unused1; + uint16_t num_sectors; /**< Sector count of the image */ + uint32_t image_lsn; /**< Start address of the image */ + uint8_t unused2[20]; +} GNUC_PACKED; + +typedef struct iso9660_br_s iso9660_br_t; + PRAGMA_END_PACKED /*! \brief A data type for a list of ISO9660 @@ -582,7 +614,8 @@ extern enum iso_extension_enum_s { ISO_EXTENSION_JOLIET_LEVEL2 = 0x02, ISO_EXTENSION_JOLIET_LEVEL3 = 0x04, ISO_EXTENSION_ROCK_RIDGE = 0x08, - ISO_EXTENSION_HIGH_SIERRA = 0x10 + ISO_EXTENSION_HIGH_SIERRA = 0x10, + ISO_EXTENSION_EL_TORITO = 0x20 } iso_extension_enums; diff --git a/src/libcdio/iso9660/iso9660_fs.c b/src/libcdio/iso9660/iso9660_fs.c index bb896a53..fc05a401 100644 --- a/src/libcdio/iso9660/iso9660_fs.c +++ b/src/libcdio/iso9660/iso9660_fs.c @@ -59,6 +59,8 @@ #include "_cdio_stdio.h" #include "cdio_private.h" +#define MAX_BOOT_IMAGES 8 + /** Implementation of iso9660_t type */ struct _iso9660_s { cdio_header_t header; /**< Internal header - MUST come first. */ @@ -83,6 +85,10 @@ struct _iso9660_s { be CDIO_CD_FRAMESIZE_RAW (2352) or M2RAW_SECTOR_SIZE (2336). */ + struct { + uint32_t lsn; /**< Start LSN of an El-Torito bootable image */ + uint32_t num_sectors; /**< Number of sectors of a bootable image */ + } boot_img[MAX_BOOT_IMAGES]; int i_fuzzy_offset; /**< Adjustment in bytes to make ISO_STANDARD_ID ("CD001") come out as ISO_PVD_SECTOR (frame 16). Normally this should be 0 @@ -505,7 +511,8 @@ iso9660_ifs_read_superblock (iso9660_t *p_iso, iso_extension_mask_t iso_extension_mask) { iso9660_svd_t p_svd; /* Secondary volume descriptor. */ - int i; + iso9660_brvd_t* p_brvd = (iso9660_brvd_t*)&p_svd; /* Boot record volume descriptor. */ + int i, j, k; if (!p_iso || !iso9660_ifs_read_pvd(p_iso, &(p_iso->pvd))) return false; @@ -516,6 +523,24 @@ iso9660_ifs_read_superblock (iso9660_t *p_iso, for (i=1; (0 != iso9660_iso_seek_read (p_iso, &p_svd, ISO_PVD_SECTOR+i, 1)); i++) { if (ISO_VD_END == from_711(p_svd.type) ) /* Last SVD */ break; + if (iso_extension_mask & ISO_EXTENSION_EL_TORITO) { + /* Check for an El-Torito boot volume descriptor */ + if (ISO_VD_BOOT_RECORD == from_711(p_svd.type) && + (memcmp(p_brvd->system_id, EL_TORITO_ID, ISO_MAX_SYSTEM_ID) == 0)) { + /* Perform very basic parsing of boot entries to fill an image table */ + iso9660_br_t br[ISO_BLOCKSIZE / sizeof(iso9660_br_t)]; + if (iso9660_iso_seek_read(p_iso, &br, p_brvd->boot_catalog_sector, 1) == ISO_BLOCKSIZE) { + for (j = 0, k = 0; + j < (ISO_BLOCKSIZE / sizeof(iso9660_br_t)) && k < MAX_BOOT_IMAGES; + j++) { + if (br[j].boot_id == 0x88 && br[j].media_type == 0) { + p_iso->boot_img[k].lsn = br[j].image_lsn; + p_iso->boot_img[k++].num_sectors = br[j].num_sectors; + } + } + } + } + } if ( ISO_VD_SUPPLEMENTARY == from_711(p_svd.type) ) { /* We're only interested in Joliet => make sure the SVD isn't overwritten */ if (p_iso->u_joliet_level == 0) @@ -1441,6 +1466,28 @@ iso9660_fs_stat_translate (CdIo_t *p_cdio, const char psz_path[]) iso9660_stat_t * iso9660_ifs_stat_translate (iso9660_t *p_iso, const char psz_path[]) { + /* Special case for virtual El-Torito boot images ('[BOOT]/#.img') */ + if (psz_path && (strncmp(psz_path, "[BOOT]/", 7) == 0)) { + int index = psz_path[7] - '0'; + iso9660_stat_t* p_stat; + if (strlen(psz_path) < 8) + return NULL; + if ((psz_path[7] < '0') || (psz_path[7] > '0' + MAX_BOOT_IMAGES - 1)) + return NULL; + if (p_iso->boot_img[index].lsn == 0 || p_iso->boot_img[index].num_sectors == 0) + return NULL; + p_stat = calloc(1, sizeof(iso9660_stat_t) + strlen(psz_path)); + if (!p_stat) { + cdio_warn("Couldn't calloc(1, %d)", (int)sizeof(iso9660_stat_t)); + return NULL; + } + p_stat->lsn = p_iso->boot_img[index].lsn; + p_stat->total_size = p_iso->boot_img[index].num_sectors * ISO_BLOCKSIZE; + p_stat->type = _STAT_FILE; + strcpy(p_stat->filename, psz_path); + return p_stat; + } + return fs_stat_translate(p_iso, (stat_root_t *) _ifs_stat_root, (stat_traverse_t *) _fs_iso_stat_traverse, psz_path); diff --git a/src/rufus.rc b/src/rufus.rc index 9737005a..a0533336 100644 --- a/src/rufus.rc +++ b/src/rufus.rc @@ -33,7 +33,7 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL IDD_DIALOG DIALOGEX 12, 12, 232, 326 STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU EXSTYLE WS_EX_ACCEPTFILES -CAPTION "Rufus 4.4.2099" +CAPTION "Rufus 4.4.2100" FONT 9, "Segoe UI Symbol", 400, 0, 0x0 BEGIN LTEXT "Drive Properties",IDS_DRIVE_PROPERTIES_TXT,8,6,53,12,NOT WS_GROUP @@ -392,8 +392,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 4,4,2099,0 - PRODUCTVERSION 4,4,2099,0 + FILEVERSION 4,4,2100,0 + PRODUCTVERSION 4,4,2100,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -411,13 +411,13 @@ BEGIN VALUE "Comments", "https://rufus.ie" VALUE "CompanyName", "Akeo Consulting" VALUE "FileDescription", "Rufus" - VALUE "FileVersion", "4.4.2099" + VALUE "FileVersion", "4.4.2100" VALUE "InternalName", "Rufus" VALUE "LegalCopyright", "© 2011-2024 Pete Batard (GPL v3)" VALUE "LegalTrademarks", "https://www.gnu.org/licenses/gpl-3.0.html" VALUE "OriginalFilename", "rufus-4.4.exe" VALUE "ProductName", "Rufus" - VALUE "ProductVersion", "4.4.2099" + VALUE "ProductVersion", "4.4.2100" END END BLOCK "VarFileInfo"