Since you agree, I thought it would be worth trying. The most useful way
to set it up is probably to use an assembler. That way, the image can
include data structures and code as needed.
I had a go at it and the resulting program is below. The generated file
will mount as an image as FAT12 /and/ can be manipulated with fdisk,
which is cool, if a bit weird!
To recap, the basic idea is to put it and some boot code at the start of
something like a USB flash memory so as to maximise the number of BIOSes
that will be able to boot it. As a guess, if the BIOS's USB boot option
were to be set to USB-FDD it should boot as a floppy (DL=0 and with the
specified FAT12 geometry) or if the BIOS were set to USB-HDD it should
boot as a hard disk (DL=0x80 but I am not sure what geometry settings it
would use; in layout terms it assumes the "defaults" of 63 sectors per
track and 255 tracks per cylinder). A BIOS set to USB boot (without
specifying -FDD or -HDD) should, hopefully, autodetect one of the above.
All untested as yet.
If more boot-code space is needed (quite likely) that can easily be made
available by making RESERVED_SECTORS higher than 1.
Feedback from any of you guys would be welcome. If you have a means of
testing it, does it work in practice? Any changes needed? Any queries on
it?
The code follows. I called it hyimg.nasm.
;**********************************************************************
;
; Produce a hybrid FDD/HDD image
;
;**********************************************************************
;Assemble to produce a disk image which can be seen as either
;a hard disk or a floppy disk.
;
;Basic layout of the image:
;
; 1 sector Combined hard-disk MBR and FAT-12 floppy VBR
; 2879 sectors The remainder of a 1.4Mbyte floppy image
; Padding sectors Padding to complete a dummy partition
;
;That can be followed by the first usable hard-disk partition.
;
;The MBR's partition table will have an entry which reserves
;the space occupied by the floppy and some padding. The padding
;will get to a boundary which is suitably aligned for the first
;real, usable partition.
;The image is to be bootable either as a floppy disk or as a
;hard disk.
;
;Configure the parameters by changing the master constants,
;below, and then build with
;
; nasm -f bin -O 2 hyimg.nasm -o hybrid.img
;
;There are various ways the generated image file could be
;used. If could be copied to the start of a device such as
;a USB flash memory unit. It could be extended by adding
;sectors at the end (e.g. with dd and >>). Or this Nasm file
;could be included from within another Nasm file which appends
;bytes for one or more partitions (which would need to be
;added to the partition table).
;Master constants
%define DUMMY_PARTITION_KB 4096 ;Size of the dummy partition
%define DUMMY_PARTITION_TYPE 0xda ;Dummy partition typecode
%define FAT_MEDIA_TYPE 0xf0 ;Filesystem media type
%define FATS 2 ;Number of FATs
%define FLOPPY_SECTORS 2880 ;Sectors in the floppy image
%define HD_SEC_PER_TRK 63 ;Sectors per HD track
%define HD_TRK_PER_CYL 255 ;Tracks per HD cylinder
%define HIDDEN_SECTORS 0 ;Sectors prior to this sector
%define INITIAL_LBA 1 ;Dummy partition's initial LBA
%define OEM_NAME "jasscl02" ;OEM name
%define PTAB_OFFSET 446 ;Partition-table offset in the MBR
%define RESERVED_SECTORS 1 ;Sectors before the 1st FAT
%define ROOTDIR_SECTORS 14 ;Sectors in the root directory
%define ROOTENTRY_SIZE 32 ;Size of each entry in the rootdir
%define SECSIZE_LOG2 9 ;Binary alignment of sector size
%define SECTORS_PER_CLUSTER 1 ;Sectors per cluster
%define SECTORS_PER_FAT 9 ;Sectors per FAT
%define SECTORS_PER_TRACK 18 ;Sectors per track
%define TRACKS_PER_CYLINDER 2 ;Tracks per cylinder, aka heads
%define VOLUME_ID 0x12345678 ;Volume ID
%define VOLUME_LABEL "NO NAME " ;Volume label
;Derived constants
%assign SECTORS_PER_CYLINDER SECTORS_PER_TRACK * TRACKS_PER_CYLINDER
%assign HD_SEC_PER_CYL HD_SEC_PER_TRK * HD_TRK_PER_CYL
%assign FINAL_LBA ((DUMMY_PARTITION_KB * 1024) >> SECSIZE_LOG2) - 1
%assign ICYL INITIAL_LBA / HD_SEC_PER_CYL
%assign rest INITIAL_LBA % HD_SEC_PER_CYL
%assign ITRK rest / HD_SEC_PER_TRK
%assign ISEC rest % HD_SEC_PER_TRK + 1
%assign FCYL FINAL_LBA / HD_SEC_PER_CYL
%assign rest FINAL_LBA % HD_SEC_PER_CYL
%assign FTRK rest / HD_SEC_PER_TRK
%assign FSEC rest % HD_SEC_PER_TRK + 1
;**********************************************************************
;
; Code start
;
;**********************************************************************
cpu 8086
boottop:
jmp short bootstart ;Standard jump (see FAT12 spec)
nop ;Standard filler (see FAT12 spec)
BS_OEMName db OEM_NAME
BPB_BytsPerSec dw 1 << SECSIZE_LOG2
BPB_SecPerClus db SECTORS_PER_CLUSTER
BPB_RsvdSecCnt dw RESERVED_SECTORS
BPB_NumFATs db FATS
BPB_RootEntCnt dw (ROOTDIR_SECTORS << SECSIZE_LOG2) / ROOTENTRY_SIZE
BPB_TotSec16 dw FLOPPY_SECTORS
BPB_Media db FAT_MEDIA_TYPE
BPB_FATSz16 dw SECTORS_PER_FAT
BPB_SecPerTrk dw SECTORS_PER_TRACK
BPB_NumHeads dw TRACKS_PER_CYLINDER
BPB_HiddSec dd HIDDEN_SECTORS
BPB_TotSec32 dd 0 ;Zero says to use BPB_TotSec16
BS_DrvNum db 0x00 ;Zero means floppy
BS_Reserved1 db 0
BS_BootSig db 0x29 ;Indicates the next 3 fields are present
BS_VolID dd VOLUME_ID
BS_VolLab db VOLUME_LABEL
BS_FilSysType db "FAT12 "
%if BPB_BytsPerSec - BS_OEMName <> 8
%error "OEM name is the wrong size"
%endif
%if $ - BS_OEMName <> 59
%error "Geometry table as defined in this code has the wrong size"
%endif
%if BS_OEMName - boottop <> 3
%error "Geometry table is in the wrong place"
%endif
;**********************************************************************
;
; Boot code
;
;**********************************************************************
bootstart:
;Boot code goes here
;%include hyboot.nasm
;**********************************************************************
;
; Partition table for when the image is seen as a hard disk
;
;**********************************************************************
;Pad to partition table
times PTAB_OFFSET - $ + boottop db 0
;The entry for the dummy partition
db 0x00 ;Bootable/not-bootable indicator byte
db ITRK
db ((ICYL >> 2) & 0xc0) | (ISEC & 0x3f)
db ICYL & 0xff
db DUMMY_PARTITION_TYPE ;Type of this partition
db FTRK
db ((FCYL >> 2) & 0xc0) | (FSEC & 0x3f)
db FCYL & 0xff
dd INITIAL_LBA ;Start sector
dd FINAL_LBA - INITIAL_LBA + 1 ;No of sectors
;The other partitions
times 3 * 16 db 0
;**********************************************************************
;
; Boot signature
;
;**********************************************************************
;The boot signature
db 0x55, 0xaa
;**********************************************************************
;
; Other reserved sectors, can contain loadable code
;
;**********************************************************************
times (RESERVED_SECTORS << SECSIZE_LOG2) - $ + boottop db 0
;**********************************************************************
;
; FATs
;
;**********************************************************************
%rep FATS
db 0xf8, 0xff, 0xff
times 0xa00 - 3 db 0
%endrep
;**********************************************************************
;
; Root directory
;
;**********************************************************************
times ROOTDIR_SECTORS << SECSIZE_LOG2 db 0
;**********************************************************************
;
; Rest of the floppy image
;
;**********************************************************************
times (FLOPPY_SECTORS << SECSIZE_LOG2) - $ + boottop db 0
;**********************************************************************
;
; Padding to the end of the dummy partition
;
;**********************************************************************
times DUMMY_PARTITION_KB * 1024 - $ + boottop db 0
;**********************************************************************
;
; First usable partition starts here
;
;**********************************************************************
--
James Harris