[SOLVED] xorriso changes isolinux.bin
by andygoth from LinuxQuestions.org on (#5JPZW)
(Not really a question, just some research I did today and want to share.)
When I create a Slackware installer image, I notice the isolinux.bin inside the image is slightly different from the isolinux.bin that I started with. Here are the first 64 bytes of pat's isolinux.bin:
Code:00000000: faea 6c7c 0000 9090 1000 0000 5b05 0000 ..l|........[...
00000010: 0060 0000 f6e7 0191 0000 0000 0000 0000 .`..............
00000020: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000030: 0000 0000 0000 0000 0000 0000 0000 0000 ................And here's how it looks after xorriso/mkisofs gets done with it:
Code:00000000: faea 6c7c 0000 9090 1000 0000 1607 0000 ..l|............
00000010: 0060 0000 f6e7 0191 0000 0000 0000 0000 .`..............
00000020: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000030: 0000 0000 0000 0000 0000 0000 0000 0000 ................The only difference I can find throughout the entire file (in fact, throughout the entire disc) is the 5b05 changing to 1607. This messes up the manifest checksums I'm trying to incorporate into my custom installers.
To confirm it's not just me, I re-downloaded the 14.2 DVD and compared its isolinux.bin with the one in the file tree. Sure enough, they have the same discrepancy. The isolinux.bin inside the installer DVD image matches the one I made today, whereas the isolinux.bin in the file tree matches the one I tried to put in my image.
I had a look at the 32-bit Slackware CD image versus its file tree isolinux.bin and observed the same thing. The 32-bit Slackware CD image has a value of 6801, whereas the 32- and 64-bit Slackware file trees have the same isolinux.bin.
Digging into the Xorriso sources, I found what's happening. In eltorito.c, make_boot_info_table() puts a struct boot_info_table eight bytes into its buffer, which ends up being isolinux.bin. Four bytes into the structure (therefore twelve bytes into the file) is found the 32-bit LBA (logical block address) of the boot file, isolinux.bin. The LBA is the raw location of isolinux.bin divided by 2048. Therefore, when I see bytes 1607 0000, that translates to 0x716 (little-endian). Multiply by 2048 for 0x38b000. Seek to that location in the resultant disc image, and sure enough we find a familiar pattern: faea 6c7c 0000 9090 1000 0000 1607 0000. Mystery solved!
Unsurprisingly, that same byte sequence (1607 0000) shows up in the generated boot.cat. Chasing the rabbit some more, I see that block 0x11 (again, blocks are 2048 bytes) contains the string "EL TORITO SPECIFICATION" as well as byte sequence 4504 0000, which in turn is 0x445 or byte location 0x222800, at which I find the boot catalog. Clearly, these numbers can change depending on file size and ordering, so isolinux.bin will not be patched the same every time.
In summary, block 0x11 is read to find the boot catalog, which in turn is read to find isolinux.bin, the first 2048-byte block of which is read to find the boot code. That code is read into memory then executed, and the first thing it does (after CLI) is JMP past its boot tables to _start1. Soon thereafter it reads the rest of isolinux.bin and continues with execution. How does it know where to find the rest of itself? Well, that's thanks to its location having been patched in! In this manner, it's able to find itself without having a full ISO9660 filesystem driver on hand.
Here's one relevant part of isolinux.asm from syslinux:
Code: section .init
;;
;; Primary entry point. Because BIOSes are buggy, we only load the first
;; CD-ROM sector (2K) of the file, so the number one priority is actually
;; loading the rest.
;;
StackBuf equ STACK_TOP-44 ; 44 bytes needed for
; the bootsector chainloading
; code!
OrigESDI equ StackBuf-4 ; The high dword on the stack
StackHome equ OrigESDI
bootsec equ $
_start: ; Far jump makes sure we canonicalize the address
cli
jmp 0:_start1
times 8-($-$$) nop ; Pad to file offset 8
; This table hopefully gets filled in by mkisofs using the
; -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
bi_csum: dd 0xdeadbeef ; Checksum of boot file
bi_reserved: times 10 dd 0xdeadbeef ; Reserved
bi_end:Pretty cool stuff, if you ask me.
See also this 2007 thread in the Ubuntu forum. Someone spotted the same issue (though he claims only one byte is different, whereas I see two consecutive bytes of difference), and the response was to change mkisofs options to not change file permissions. In other words, to use -R instead of -r. Well, I'm already using -R, so that's obviously got nothing to do with it. The thread just dropped at that point, so I'm happy to finally provide a real answer, 14 years later.
When I create a Slackware installer image, I notice the isolinux.bin inside the image is slightly different from the isolinux.bin that I started with. Here are the first 64 bytes of pat's isolinux.bin:
Code:00000000: faea 6c7c 0000 9090 1000 0000 5b05 0000 ..l|........[...
00000010: 0060 0000 f6e7 0191 0000 0000 0000 0000 .`..............
00000020: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000030: 0000 0000 0000 0000 0000 0000 0000 0000 ................And here's how it looks after xorriso/mkisofs gets done with it:
Code:00000000: faea 6c7c 0000 9090 1000 0000 1607 0000 ..l|............
00000010: 0060 0000 f6e7 0191 0000 0000 0000 0000 .`..............
00000020: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000030: 0000 0000 0000 0000 0000 0000 0000 0000 ................The only difference I can find throughout the entire file (in fact, throughout the entire disc) is the 5b05 changing to 1607. This messes up the manifest checksums I'm trying to incorporate into my custom installers.
To confirm it's not just me, I re-downloaded the 14.2 DVD and compared its isolinux.bin with the one in the file tree. Sure enough, they have the same discrepancy. The isolinux.bin inside the installer DVD image matches the one I made today, whereas the isolinux.bin in the file tree matches the one I tried to put in my image.
I had a look at the 32-bit Slackware CD image versus its file tree isolinux.bin and observed the same thing. The 32-bit Slackware CD image has a value of 6801, whereas the 32- and 64-bit Slackware file trees have the same isolinux.bin.
Digging into the Xorriso sources, I found what's happening. In eltorito.c, make_boot_info_table() puts a struct boot_info_table eight bytes into its buffer, which ends up being isolinux.bin. Four bytes into the structure (therefore twelve bytes into the file) is found the 32-bit LBA (logical block address) of the boot file, isolinux.bin. The LBA is the raw location of isolinux.bin divided by 2048. Therefore, when I see bytes 1607 0000, that translates to 0x716 (little-endian). Multiply by 2048 for 0x38b000. Seek to that location in the resultant disc image, and sure enough we find a familiar pattern: faea 6c7c 0000 9090 1000 0000 1607 0000. Mystery solved!
Unsurprisingly, that same byte sequence (1607 0000) shows up in the generated boot.cat. Chasing the rabbit some more, I see that block 0x11 (again, blocks are 2048 bytes) contains the string "EL TORITO SPECIFICATION" as well as byte sequence 4504 0000, which in turn is 0x445 or byte location 0x222800, at which I find the boot catalog. Clearly, these numbers can change depending on file size and ordering, so isolinux.bin will not be patched the same every time.
In summary, block 0x11 is read to find the boot catalog, which in turn is read to find isolinux.bin, the first 2048-byte block of which is read to find the boot code. That code is read into memory then executed, and the first thing it does (after CLI) is JMP past its boot tables to _start1. Soon thereafter it reads the rest of isolinux.bin and continues with execution. How does it know where to find the rest of itself? Well, that's thanks to its location having been patched in! In this manner, it's able to find itself without having a full ISO9660 filesystem driver on hand.
Here's one relevant part of isolinux.asm from syslinux:
Code: section .init
;;
;; Primary entry point. Because BIOSes are buggy, we only load the first
;; CD-ROM sector (2K) of the file, so the number one priority is actually
;; loading the rest.
;;
StackBuf equ STACK_TOP-44 ; 44 bytes needed for
; the bootsector chainloading
; code!
OrigESDI equ StackBuf-4 ; The high dword on the stack
StackHome equ OrigESDI
bootsec equ $
_start: ; Far jump makes sure we canonicalize the address
cli
jmp 0:_start1
times 8-($-$$) nop ; Pad to file offset 8
; This table hopefully gets filled in by mkisofs using the
; -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
bi_csum: dd 0xdeadbeef ; Checksum of boot file
bi_reserved: times 10 dd 0xdeadbeef ; Reserved
bi_end:Pretty cool stuff, if you ask me.
See also this 2007 thread in the Ubuntu forum. Someone spotted the same issue (though he claims only one byte is different, whereas I see two consecutive bytes of difference), and the response was to change mkisofs options to not change file permissions. In other words, to use -R instead of -r. Well, I'm already using -R, so that's obviously got nothing to do with it. The thread just dropped at that point, so I'm happy to finally provide a real answer, 14 years later.