[syslinux:pathbased] iso9660: use boot_info_table and fix hybrid mode
syslinux-bot for H. Peter Anvin
hpa at zytor.com
Fri Feb 26 13:21:25 PST 2010
Commit-ID: 3e89b30bfa7b90d785d8f97ea5638a7b63e12c94
Gitweb: http://syslinux.zytor.com/commit/3e89b30bfa7b90d785d8f97ea5638a7b63e12c94
Author: H. Peter Anvin <hpa at zytor.com>
AuthorDate: Fri, 26 Feb 2010 13:18:26 -0800
Committer: H. Peter Anvin <hpa at zytor.com>
CommitDate: Fri, 26 Feb 2010 13:18:26 -0800
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 at zytor.com>
---
core/fs/iso9660/iso9660.c | 31 +++++++++++++++++++------------
core/fs/iso9660/iso9660_fs.h | 11 +++++++++++
core/isolinux.asm | 2 ++
3 files changed, 32 insertions(+), 12 deletions(-)
diff --git a/core/fs/iso9660/iso9660.c b/core/fs/iso9660/iso9660.c
index c32c3a0..995cd21 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 6e9d495..a365fa1 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 078f7ca..7329f14 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
More information about the Syslinux-commits
mailing list