aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2010-02-26 13:18:26 -0800
committerH. Peter Anvin <hpa@zytor.com>2010-02-26 13:18:26 -0800
commit3e89b30bfa7b90d785d8f97ea5638a7b63e12c94 (patch)
tree8a2a2a1395f1d45b4b948bbbe217237af636d460
parent1a59dd9ed50ac9b853cbcbf005be6759dcd7f066 (diff)
downloadsyslinux.git-3e89b30bfa7b90d785d8f97ea5638a7b63e12c94.tar.gz
syslinux.git-3e89b30bfa7b90d785d8f97ea5638a7b63e12c94.tar.xz
syslinux.git-3e89b30bfa7b90d785d8f97ea5638a7b63e12c94.zip
iso9660: use boot_info_table and fix hybrid mode
In hybrid disk mode, one block will generally *not* equal one sector. Use the boot_info_table to find the primary volume descriptor. Remove the now-unused cdrom_read_blocks(). Signed-off-by: H. Peter Anvin <hpa@zytor.com>
-rw-r--r--core/fs/iso9660/iso9660.c31
-rw-r--r--core/fs/iso9660/iso9660_fs.h11
-rw-r--r--core/isolinux.asm2
3 files changed, 32 insertions, 12 deletions
diff --git a/core/fs/iso9660/iso9660.c b/core/fs/iso9660/iso9660.c
index c32c3a0b..995cd21f 100644
--- a/core/fs/iso9660/iso9660.c
+++ b/core/fs/iso9660/iso9660.c
@@ -134,12 +134,6 @@ static bool iso_compare_name(const char *de_name, size_t len,
return true;
}
-static inline int cdrom_read_blocks(struct disk *disk, void *buf,
- int block, int blocks)
-{
- return disk->rdwr_sectors(disk, buf, block, blocks, 0);
-}
-
/*
* Find a entry in the specified dir with name _dname_.
*/
@@ -314,25 +308,38 @@ static int iso_load_config(void)
return 0;
}
-
static int iso_fs_init(struct fs_info *fs)
{
struct iso_sb_info *sbi;
-
+ char pvd[2048]; /* Primary Volume Descriptor */
+ uint32_t pvd_lba;
+ struct disk *disk = fs->fs_dev->disk;
+ int blktosec;
+
sbi = malloc(sizeof(*sbi));
if (!sbi) {
malloc_error("iso_sb_info structure");
return 1;
}
fs->fs_info = sbi;
-
- cdrom_read_blocks(fs->fs_dev->disk, trackbuf, 16, 1);
- memcpy(&sbi->root, trackbuf + ROOT_DIR_OFFSET, sizeof(sbi->root));
+ /*
+ * XXX: handling iso9660 in hybrid mode on top of a 4K-logical disk
+ * will really, really hurt...
+ */
fs->sector_shift = fs->fs_dev->disk->sector_shift;
- fs->block_shift = 11;
+ fs->block_shift = 11; /* A CD-ROM block is always 2K */
fs->sector_size = 1 << fs->sector_shift;
fs->block_size = 1 << fs->block_shift;
+ blktosec = fs->block_shift - fs->sector_shift;
+
+ pvd_lba = iso_boot_info.pvd;
+ if (!pvd_lba)
+ pvd_lba = 16; /* Default if not otherwise defined */
+
+ disk->rdwr_sectors(disk, pvd, (sector_t)pvd_lba << blktosec,
+ 1 << blktosec, false);
+ memcpy(&sbi->root, pvd + ROOT_DIR_OFFSET, sizeof(sbi->root));
/* Initialize the cache */
cache_init(fs->fs_dev, fs->block_shift);
diff --git a/core/fs/iso9660/iso9660_fs.h b/core/fs/iso9660/iso9660_fs.h
index 6e9d495c..a365fa1a 100644
--- a/core/fs/iso9660/iso9660_fs.h
+++ b/core/fs/iso9660/iso9660_fs.h
@@ -4,6 +4,17 @@
#include <klibc/compiler.h>
#include <stdint.h>
+/* Boot info table */
+struct iso_boot_info {
+ uint32_t pvd; /* LBA of primary volume descriptor */
+ uint32_t file; /* LBA of boot file */
+ uint32_t length; /* Length of boot file */
+ uint32_t csum; /* Checksum of boot file */
+ uint32_t reserved[10]; /* Currently unused */
+};
+
+extern struct iso_boot_info iso_boot_info; /* In isolinux.asm */
+
/* The root dir entry offset in the primary volume descriptor */
#define ROOT_DIR_OFFSET 156
diff --git a/core/isolinux.asm b/core/isolinux.asm
index 078f7ca7..7329f145 100644
--- a/core/isolinux.asm
+++ b/core/isolinux.asm
@@ -200,6 +200,8 @@ _start: ; Far jump makes sure we canonicalize the address
; -boot-info-table option. If not, the values in this
; table are default values that we can use to get us what
; we need, at least under a certain set of assumptions.
+ global iso_boot_info
+iso_boot_info:
bi_pvd: dd 16 ; LBA of primary volume descriptor
bi_file: dd 0 ; LBA of boot file
bi_length: dd 0xdeadbeef ; Length of boot file