chain, options: bugfixes, adjustments; big doc update
authorMichal Soltys <soltys@ziu.info>
Thu, 26 Aug 2010 07:21:55 +0000 (09:21 +0200)
committerMichal Soltys <soltys@ziu.info>
Tue, 28 Sep 2010 07:32:52 +0000 (09:32 +0200)
- seg='s offset values default to 0 if ommited
- sect='s offset values default to 0x7c00 if ommited
- FDOS's bootsector loaded at 0x1fe0
- drive / partition parsing: bugfix, so lables with ',' are recognized
  properly
- big documentation update

Signed-off-by: Michal Soltys <soltys@ziu.info>
com32/chain/chain.c
com32/chain/options.c
com32/chain/options.h
doc/chain.txt

index 12372aa..e983dcb 100644 (file)
@@ -378,7 +378,7 @@ static int pem_setchs(const struct disk_info *di,
        *(uint32_t *)dp->end != ochs2;
 }
 
-static int pe_mangle(struct part_iter *_iter)
+static int pentry_mangle(struct part_iter *_iter)
 {
     int wb = 0, werr = 0;
     uint32_t cebr_lba = 0;
@@ -522,7 +522,7 @@ int find_dp(struct part_iter **_iter)
     }
     /* main options done - only thing left is explicit partition specification,
      * if we're still at the disk stage with the iterator AND user supplied
-     * partition number (including disk).
+     * partition number (including disk pseudo-partition).
      */
     if (!iter->index && opt.partition) {
        partition = strtol(opt.partition, NULL, 0);
@@ -713,7 +713,7 @@ int main(int argc, char *argv[])
 
     /* Perform initial partition entry mangling */
     if (opt.hide || opt.mbrchs)
-       pe_mangle(iter);
+       pentry_mangle(iter);
 /*     hide_unhide(iter);*/
 
     /* Load the boot file */
@@ -817,6 +817,7 @@ int main(int argc, char *argv[])
        if (try_mangles_bpb(iter, data + sidx))
            goto bail;
 
+       /* This *must* be after BPB mangling */
        if (opt.cmldr && mangles_cmldr(data + sidx))
            goto bail;
     }
index f12a975..6fb07fd 100644 (file)
@@ -8,11 +8,15 @@
 
 int soi_s2n(char *ptr, unsigned int *seg,
                       unsigned int *off,
-                      unsigned int *ip)
+                      unsigned int *ip,
+                      unsigned int def)
 {
-    unsigned int segval = 0, offval = 0x7c00, ipval = 0x7c00, val;
+    unsigned int segval = 0, offval, ipval, val;
     char *p;
 
+    offval = def;
+    ipval = def;
+
     segval = strtoul(ptr, &p, 0);
     if (p[0] == ':' && p[1] && p[1] != ':')
        offval = strtoul(p+1, &p, 0);
@@ -53,20 +57,21 @@ void usage(void)
 "\
 Usage:\n\
     chain.c32 [options]\n\
-    chain.c32 {fd|hd}<disk> [<partition>] [options]\n\
-    chain.c32 mbr{:|=}<id> [<partition>] [options]\n\
-    chain.c32 guid{:|=}<guid> [<partition>] [options]\n\
-    chain.c32 label{:|=}<label> [<partition>] [options]\n\
-    chain.c32 boot{,| }[<partition>] [options]\n\
+    chain.c32 {fd|hd}<disk>{,| }[<part#>] [options]\n\
+    chain.c32 mbr{:|=}<id>{, | }[<part#>] [options]\n\
+    chain.c32 guid{:|=}<guid>{,| }[<part#>] [options]\n\
+    chain.c32 label{:|=}<label> [<part#>] [options]\n\
+    chain.c32 boot{,| }[<part#>] [options]\n\
     chain.c32 fs [options]\n\
 ", "\
-\nOptions ('no' prefix specify default value):\n\
-    file=<loader>        Load and execute file\n\
+\nOptions #1 ('no' prefix specifies default value):\n\
+    file=<file>          Load and execute <file>\n\
     seg=<s[:o[:i]]>      Load file at <s:o>, jump to <s:i>\n\
-    nofilebpb            Treat file in memory as BPB compatible\n\
+                         - defaults to 0:0x7C00:0x7C00\n\
+                         - ommited o/i values default to 0\n\
     sect[=<s[:o[:i]]>]   Load sector at <s:o>, jump to <s:i>\n\
                          - defaults to 0:0x7C00:0x7C00\n\
-                         - ommited o/i values default 0x7C00\n\
+                         - ommited o/i values default to 0x7C00\n\
     maps                 Map loaded sector into real memory\n\
     nosethid[den]        Set BPB's hidden sectors field\n\
     nosetgeo             Set BPB's sectors per track and heads fields\n\
@@ -74,6 +79,9 @@ Usage:\n\
                          - <off> defaults to autodetection\n\
                          - only 0x24 and 0x40 are accepted\n\
     nosetbpb             Enable set{hid,geo,drv}\n\
+    nofilebpb            Treat file in memory as BPB compatible\n\
+", "\
+\nOptions #2 ('no' prefix specifies default value):\n\
     nosave               Write adjusted sector back to disk\n\
     hand                 Prepare handover area\n\
     nohptr               Force ds:si and ds:bp to point to handover area\n\
@@ -85,7 +93,7 @@ Usage:\n\
     nowarn               Wait for a keypress to continue chainloading\n\
                          - useful to see emited warnings\n\
 ", "\
-\nComposite options:\n\
+\nOptions #3 ('no' prefix specifies default value):\n\
     isolinux=<loader>    Load another version of ISOLINUX\n\
     ntldr=<loader>       Load Windows NTLDR, SETUPLDR.BIN or BOOTMGR\n\
     cmldr=<loader>       Load Recovery Console of Windows NT/2K/XP/2003\n\
@@ -122,7 +130,7 @@ int parse_args(int argc, char *argv[])
        } else if (!strcmp(argv[i], "nofile")) {
            opt.file = NULL;
        } else if (!strncmp(argv[i], "seg=", 4)) {
-           if (soi_s2n(argv[i] + 4, &opt.fseg, &opt.foff, &opt.fip))
+           if (soi_s2n(argv[i] + 4, &opt.fseg, &opt.foff, &opt.fip, 0))
                goto bail;
        } else if (!strncmp(argv[i], "bss=", 4)) {
            opt.file = argv[i] + 4;
@@ -132,6 +140,7 @@ int parse_args(int argc, char *argv[])
            opt.setdrv = true;
            opt.drvoff = ~0u;
            opt.filebpb = true;
+           /* opt.save = true; */
        } else if (!strncmp(argv[i], "isolinux=", 9)) {
            opt.file = argv[i] + 9;
            opt.isolinux = true;
@@ -164,9 +173,7 @@ int parse_args(int argc, char *argv[])
            opt.fseg = 0x60;    /* FREEDOS wants this address */
            opt.foff = 0;
            opt.fip = 0;
-           opt.sseg = 0x9000;
-           opt.soff = 0;
-           opt.sip = 0;
+           opt.sseg = 0x1FE0;
            opt.file = argv[i] + 8;
            opt.sethid = true;
            opt.setgeo = true;
@@ -180,9 +187,7 @@ int parse_args(int argc, char *argv[])
            opt.fseg = 0x70;    /* MS-DOS 2.00 .. 6.xx wants this address */
            opt.foff = 0;
            opt.fip = v == 7 ? 0x200 : 0;  /* MS-DOS 7.0+ wants this ip */
-           opt.sseg = 0x9000;
-           opt.soff = 0;
-           opt.sip = 0;
+           opt.sseg = 0x8000;
            opt.file = argv[i] + v;
            opt.sethid = true;
            opt.setgeo = true;
@@ -288,7 +293,7 @@ int parse_args(int argc, char *argv[])
        } else if (!strncmp(argv[i], "sect=", 5) ||
                   !strcmp(argv[i], "sect")) {
            if (argv[i][4]) {
-               if (soi_s2n(argv[i] + 5, &opt.sseg, &opt.soff, &opt.sip))
+               if (soi_s2n(argv[i] + 5, &opt.sseg, &opt.soff, &opt.sip, 0x7c00))
                    goto bail;
                if ((opt.sseg << 4) + opt.soff + SECTOR - 1 > ADDRMAX) {
                    error("Arguments of 'sect=' are invalid - resulting address too big.\n");
@@ -326,13 +331,15 @@ int parse_args(int argc, char *argv[])
                   || !strncmp(argv[i], "boot,", 5)
                   || !strcmp(argv[i], "fs")) {
            opt.drivename = argv[i];
-           p = strchr(opt.drivename, ',');
-           if (p) {
-               *p = '\0';
-               opt.partition = p + 1;
-           } else if (argv[i + 1] && argv[i + 1][0] >= '0'
-                      && argv[i + 1][0] <= '9') {
-               opt.partition = argv[++i];
+           if (strncmp(argv[i], "label", 5)) {
+               p = strchr(opt.drivename, ',');
+               if (p) {
+                   *p = '\0';
+                   opt.partition = p + 1;
+               } else if (argv[i + 1] && argv[i + 1][0] >= '0'
+                       && argv[i + 1][0] <= '9') {
+                   opt.partition = argv[++i];
+               }
            }
        } else {
            usage();
index e400eca..acd50e6 100644 (file)
@@ -1,7 +1,8 @@
 #ifndef _COM32_CHAIN_OPTIONS_H
 #define _COM32_CHAIN_OPTIONS_H
 
-int soi_s2n(char *ptr, unsigned int *seg, unsigned int *off, unsigned int *ip);
+int soi_s2n(char *ptr, unsigned int *seg, unsigned int *off,
+       unsigned int *ip, unsigned int def);
 void usage(void);
 int parse_args(int argc, char *argv[]);
 
index 5cba3a5..5f28fbe 100644 (file)
                            chain.c32 documentation
 
 Although syslinux is capable of (very simple) native chainloading (through .bss
-and .bs options - see doc/syslinux.txt), it also has a very roboust and
-feature-rich com32 module designed for such purpose. This module should allow
-you to boot virtually anything.
+and .bs options - see doc/syslinux.txt), it also features a very roboust and
+rich com32 module designed for such purpose.
 
+Chain module can perform few basic tasks:
 
-!FIXME: initial move from chain.c below
+- load and jump to a sector
+- load and jump to a file (also loading a sector for other purposes)
+- prepare handover data to use by a file / boot sector
+- fix different options in a file / sector / partition entries
 
+It can chainload data from both GPT and DOS partitions, as well as boot the
+first sector from a raw disk.
 
-Chainload a hard disk.
+In more details, the flow of code is as follows:
 
-Usage: chain [options]
-       chain hd<disk#> [<partition>] [options]
-       chain fd<disk#> [options]
-       chain mbr:<id> [<partition>] [options]
-       chain guid:<guid> [<partition>] [options]
-       chain label:<label> [<partition>] [options]
-       chain boot [<partition>] [options]
+1.  Parse arguments.
+2.  Find drive and/or partition to boot from.
+3.  Hide / unhide systems and/or fix chs values in partition entries on the
+    drive syslinux is booting from (options: 'hide', 'hideall', 'mbrchs').
+4.  Load file to boot from (options: 'file', 'seg').
+5.  Load sector to boot from (options: 'sect', 'maps'), if it doesn't conflict
+    with #5.
+6.  Prepare handover area (options: 'hand', 'maps'), if it doesn't conflict
+    with #5 & #6, and syslinux is booting a partition.
+7.  Adjust ds:si and ds:bp to point to either a handover, a sector (options:
+    'hptr', 'maps', 'sect', 'file') or nowhere.
+8.  Patch loaded file if necessary ('isolinux', 'grub', 'grldr', 'filebpb')
+9.  Patch loaded sector if necessary ('setdrv', 'sethid', 'setgeo', 'setbpb',
+    'save', 'cmldr')
+10. Chainload (options: 'swap').
 
-For example, "chain msdos=io.sys" will load DOS from the current Syslinux
-filesystem.  "chain hd0 1" will boot the first partition on the first hard
-disk.
+In most basic form, syslinux loads specified boot sector (or mbr, if not
+specified) at 0:0x7c00, prepares handover area as a standard mbr would do, and
+jumps to 0:0x7c00.
 
-When none of the "hdX", "fdX", "mbr:", "guid:", "label:", "boot" or "fs"
-options are specified, the default behaviour is equivalent to "boot".
-"boot" means to use the current Syslinux drive, and you can also specify
-a partition.
 
-The mbr: syntax means search all the hard disks until one with a
-specific MBR serial number (bytes 440-443) is found.
+Module invocation:
 
-Partitions 1-4 are primary, 5+ logical, 0 = boot MBR (default.)
+chain [drive/partition] [options]
 
-"fs" will use the current Syslinux filesystem as the boot drive/partition.
-When booting from PXELINUX, you will most likely wish to specify a disk.
+                       DRIVE / PARTITION SPECIFICATION
 
-Options:
+Drive can be specified as 'hd#', 'fd#', 'boot', 'mbr', or 'guid'.
 
-file=<loader>
-     loads the file <loader> **from the Syslinux filesystem**
-     instead of loading the boot sector.
+- 'mbr' will select a drive by a signature.
+- 'guid' will select a drive by a guid
+- 'boot' is the drive syslinux was booted from. This is the default value, if
+  nothing else is specified.
+- 'hd#' and 'fd#' are standard ways to specify drive number as seen by bios,
+  starting from 0.
 
-seg=<segment>
-     loads at and jumps to <seg>:0000 instead of 0000:7C00.
+Option 'guid' is shared with partition selection (see below). If you happened
+to have non-unique guids, they are searched in disk0, partitions of disk0,
+disk1 ...  order.
 
-isolinux=<loader>
-     chainload another version/build of the ISOLINUX bootloader and patch
-     the loader with appropriate parameters in memory.
-     This avoids the need for the -eltorito-alt-boot parameter of mkisofs,
-     when you want more than one ISOLINUX per CD/DVD.
+The priority of those options are the same as in the above list.
 
-ntldr=<loader>
-     equivalent to seg=0x2000 file=<loader> sethidden,
-     used with WinNT's loaders
+If you specify the same value more than once, the last value will be used.
 
-cmldr=<loader>
-     used with Recovery Console of Windows NT/2K/XP.
-     same as ntldr=<loader> & "cmdcons\0" written to
-     the system name field in the bootsector
+'mbr' and 'guid' take extra parameter - you should use ':' or '=' as a
+delimiter.
 
-freedos=<loader>
-     equivalent to seg=0x60 file=<loader> sethidden,
-     used with FreeDOS' kernel.sys.
 
-msdos=<loader>
-pcdos=<loader>
-     equivalent to seg=0x70 file=<loader> sethidden,
-     used with DOS' io.sys.
+Partition can be specified as '#', 'guid', 'label' or 'fs'.
 
-grub=<loader>
-     same as seg=0x800 file=<loader> & jumping to seg 0x820,
-     used with GRUB Legacy stage2 files.
+- 'guid' option will select a partition by a guid (not a type guid !)
+- 'label' will select a partition by a label (searching is done in
+  disk order)
+- 'fs' will select a partition from which syslinux was executed
+- '#' is the standard method. Partitions 1-4 are primary, 5+ logical, 0 = boot
+  MBR (default).
 
-grubcfg=<filename>
-     set an alternative config filename in stage2 of Grub Legacy,
-     only applicable in combination with "grub=<loader>".
+The priority of those options are the same as in the above list.
 
-grldr=<loader>
-     pass the partition number to GRUB4DOS,
-     used with GRUB4DOS' grldr.
+If you use a number to select a partition it should be specified after a drive
+using space or comma as delimiters (after 'hd#', 'fd#', 'mbr', 'guid' or 'boot').
 
-swap
-     if the disk is not fd0/hd0, install a BIOS stub which swaps
-     the drive numbers.
+                                   OPTIONS
+       file=<file>
+       *nofile
 
-hide
-     change type of primary partitions with IDs 01, 04, 06, 07,
-     0b, 0c, or 0e to 1x, except for the selected partition, which
-     is converted the other way.
+It's often convenient to load a file directly and transfer control to it,
+instead of the sector from the disk. Note, that the <file> must reside on
+syslinux partition.
 
-sethidden
-     update the "hidden sectors" (partition offset) field in a
-     FAT/NTFS boot sector.
+If you choose this option without specifying any addresses explicitly (see
+options 'sect=' and 'seg='), the file will cause sector to not be loaded at all
+(as their memory placement would overlap).
 
-keeppxe
-     keep the PXE and UNDI stacks in memory (PXELINUX only).
+       seg=<segment>:<offset>:<ip>
+       *seg=0:0x7c00:0x7c00
 
+This triplet lets you alter the addresses a file will use. Loading is done to
+<segment:offset>, jumping to <segment:ip>. When you chainload some other
+bootloader or kernel, it's almost always mandatory.
 
-    file=<loader>      Load and execute file; boot sector is also\n\
-    msdos7=<loader>    Load MS-DOS 7+ IO.SYS\n\
-    seg=<s[:o[:i]]>    Load file at <s:o>, jump to <s:i>\n\
-    segbs=<s[:o[:i]]>  Load boot sector at <s:o>, jump to <s:i>;\n\
-    sethidden          Set the FAT/NTFS hidden sectors field\n\
-    setgeometry        Set the FAT/NTFS sectors per track and heads fields\n\
-    setdrive@<offset>  Set the FAT/NTFS drive unit field at <offset>;\n\
-                           setdrive option alone defaults to 0x24\n\
-    setbpb             Enable set{hidden,geometry} options\n\
-    writebs            Write updated boot sector to the disk\n\
-    filebpb            Also mangle file with bpb options\n\
-    bsnomap            Don't map boot sector into real memory.\n\
+The defaults, if option is not specified, are 0:0x7c00:0x7c00
+If some of the fields are ommited (e.g. 0x2000::), they default to 0.
+
+       sect=<segment>:<offset>:<ip>
+       nosect
+       *sect=0:0x7c00:0x7c00
+
+This triplet lets you alter the addresses a sector will use. File is loaded at
+<segment:offset>, the jump is made to <segment:ip>. This option is mostly used
+in tandem with 'file=' and 'seg=' options, as some loaders/kernels will expect
+relocated sector at some particular address (e.g. DRKM).
+
+'nosect' will cause sector to not be loaded at all. In plenty cases, when a file
+is being chainloaded, sector is not necessary.
+
+The defaults if option is not specified, are 0:0x7c00:0x7c00.
+If some of the fields are ommited (e.g. 0x2000::), segment defaults to 0,
+offset and ip to 0x7c00.
+
+       *maps
+       nomaps
+
+In some cases, it's useful to fix BPB values in NTFS/FATxx bootsectors and
+evntually write them back, but otherwise boot sector itself is not necessary to
+continue booting. 'nomaps' allows that - a sector will be loaded, but won't be
+mmapped into real memory. Any overlap tests (vs. handover or file areas) are
+not performed, being meaningless in such case.
+
+       sethid[den]
+       *nosethid[den]
+
+       setgeo
+       *nosetgeo
+
+       setdrv[@<addr>]
+       *nodrv
+
+Microsoft side of the world is paritculary bitchy about certain BPB values.
+Depending on the system and chainloading method (sector or file), some or all
+of those fields must match reality - and after e.g. drive clonning or
+when using usb stick in different computers - that is often not the case.
+
+The "reality" means:
+
+"hidden sectors" - valid offset of the partition from the beginning of the disk
+"geometry" - valid disk geometry as reported by BIOS
+"drive" - valid drive number
+
+'sethidden'
+  updates the partition offset to match the current disk position
+'setgeo'
+  updates "heads" and "sectors per track" values as reported by BIOS
+'setdrv'
+  will update the drive value at proper offset. Only 0x24 and 0x40 are
+  accepted as valid values. You can use '@', '=' and ':' as delimiters.
+  If the address is not specified, it's autodetected.
+
+       setbpb
+       *nosetbpb
+
+Handy shortcut for setdrv, setgeo and sethid.
+
+       filebpb
+       *nofilebpb
+
+Chainloaded file can simply be an image of a sector. In such case, it could be
+useful to also fix its BPB values.
+
+       save
+       *nosave
+
+Fixing BPB values only in memory might not be enough. This option allows
+writing of the corrected sector. You will probably want to use this option
+together with 'setbpb' or other ones using that implicitly. 
+
+- this option never applies to a loaded file
+- chain module will never save anything to disk by default
+- writing is only performed, if the values actually changed
+
+       hand
+       *hand
+
+By default, a handover area is always prepared if possible and potentially
+useful - meaning it doesn't overlap with other areas, and syslinux chainloads a
+partition. It's often not necessary though - usually, a chainloaded file or
+kernel don't care about it anymore, so a user can disable it explicitly with
+this option.
+
+       hptr
+       *nohptr
+
+In case when both file and sector are loaded, ds:si and ds:bp will point to
+sector address before the chainloading. This option lets user force those
+registers to point to handover area. This is useful when both the file and the
+sector are actually a sector's image and the sector is mmapped.
+
+       swap
+       *noswap
+
+This option will install a tiny stub code used to swap drive numbers, if the
+drive we use during chainloading is not fd0 or hd0.
+
+       hide[all]
+       *nohide
+
+In certain situations it's useful to hide partitions - for example to make sure
+DOS gets C:. 'hide' will hide hidable primary partitions, except the one we're
+booting from. Similary, 'hideall' will hide all hidable partitions, except the
+one we're booting from. Hiding is performed only on the boot drive.
+Writing is only performed, if the values actually changed.
+
+       mbrchs
+       *nombrchs
+
+If you want to make a drive you're booting from totally compatible with current
+BIOS, you can use this to fix all partitions' CHS numbers. Good to silence e.g.
+FreeDOS complainig about 'logical CHS differs from physcial' of sfdisk about
+'found (...) expected (...).  Functionally seems to be mostly cosmetic, as
+Microsoft world - in cases it cares about geometry - generally sticks to values
+written in bootsectors. And the rest of the world generally doesn't care about
+them at all. Writing is only performed, if the values actually changed.
+
+       keepexe
+       *nokeepexe
+
+If you're booting over a network using pxelinux - this lets you keep UNDI
+stacks in memory.
+
+       warn
+       *nowarn
+
+This option will wait for a keypress right before continuing the chainloading.
+Useful to see warnings emited by the chain module.
+
+       isolinux=<file>
+       sets: file=<file> nohand nosect
+
+Chainload another version/build of the ISOLINUX bootloader and patch the loader
+with appropriate parameters in memory. This avoids the need for the
+-eltorito-alt-boot parameter of mkisofs, when you want more than one ISOLINUX
+per CD/DVD.
+
+       ntldr=<file>
+       sets: file=<file> seg=0x2000 setbpb nohand
+
+Prepares to load ntldr directly. You might want to add 'save' option to store
+corrected BPB values.
+
+       cmldr=<file>
+       sets: file=<file> seg=0x2000 setbpb nohand
+
+Prepares to load recovery console directly. In-memory copy of bootsector is
+patched with "cmdcons\0". Remarks the same as in 'ntldr='.
+
+       freedos=<file>
+       sets: file=<file> seg=0x60 sect=0x1FE0 setbpb nohand
+
+Prepares to load freedos kernel directly. You will likely want to add 'save'
+option, as those kernels seem to require proper geometry written back to disk.
+Sector address is chosen based on where freedos' bootsectors relocate themselves,
+although it seems the kernel doesn't rely on one.
+You might also want to employ 'hide' option, if you have problems with properly
+assigned C: drive.
+
+       pcdos=<file>
+       msdos=<file>
+       sets: file=<file> seg=0x70 sect=0x8000 setbpb nohand
+
+Similary to 'freedos=', This prepares to load MSDOS 2.00 - 6.xx or derivatives.
+Sector address is chosen arbitrarily. Otherwise comments as above.
+
+       msdos7=<file>
+       sets: file=<file> seg=0x70::0x200 sect=0x8000 setbpb nohand
+
+Only for MSDOS 7+ versions (98se ~ 7.xx, millenium ~ 8.xx). Comments as above.
+TODO/TEST
+
+       drmk=<file>
+       sets: file=<file> seg=0x70 sect=0x2000:0:0 setbpb nohand
+
+This is used for loading of *only* Dell's DOS derivatives. It does require boot
+sector at 0x2000 and overall valid BPB values. As with other DOSish cases,
+likely candidates for use are 'save' and 'hide'.
+
+       grub=<file>
+       grubcfg=<config>
+       sets: file=<file> seg=0x800::0x200 nohand nosect
+
+Chainloads grub legacy's stage2, performing additional corrections on the file
+in memory. Additionally, alternate config file can be specified through
+'grubcfg=' option
+
+       grldr=<file>
+       sets: file=<file> nohand nosect
+
+Chainloads GRUB4DOS grldr, performing additional corrections on the file
+in memory.
+
+       bss=<file>
+       sets: bss=<file> nomaps setbpb filebpb
+
+This attempts to emulate syslinux's native BSS option to certain extent. This
+loads both the file and the sector and adjusts BPB values in both. As only basic BPB
+fields are corrected, both the file and the sector should be identical enough
+(except boot code, drive number, geometry, hidden sectors). Don't forget about
+'save' and 'swap' options.
+
+This will likely get expanded in future.