├── README.md ├── bootdisks ├── freedos.boot.disk.1.4MB.img ├── freedos.boot.disk.1200K.img ├── freedos.boot.disk.160K.img ├── freedos.boot.disk.180K.img ├── freedos.boot.disk.320K.img ├── freedos.boot.disk.360K.img ├── freedos.boot.disk.640K.img └── freedos.boot.disk.720K.img ├── bootsectors ├── freedos.boot.sector.1.4MB.img ├── freedos.boot.sector.1200K.img ├── freedos.boot.sector.160K.img ├── freedos.boot.sector.180K.img ├── freedos.boot.sector.320K.img ├── freedos.boot.sector.360K.img ├── freedos.boot.sector.640K.img └── freedos.boot.sector.720K.img ├── sample ├── freedos.boot.disk.160K.img ├── libv86.js ├── sample.html ├── seabios.bin └── vgabios.bin └── scripts ├── eddosboot.sh ├── hexlib.sh ├── lib ├── boot_disk_contents │ ├── AUTOEXEC.BAT │ ├── COMMAND.COM │ ├── CONFIG.SYS │ ├── KERNEL.SYS │ └── README.TXT └── v86.freedos.boot.disk.img ├── testeddosboot.sh └── testhexlib.sh /README.md: -------------------------------------------------------------------------------- 1 | # FreeDOS Boot Disks 2 | 3 | The FreeDOS Boot Disks repository contains minimal bootable [FreeDOS](http://www.freedos.org/) diskette images and [boot sectors](https://en.wikipedia.org/wiki/Boot_sector) from those diskettes. The diskette images can be used to boot a simple DOS shell in a virtual machine such as [VirtualBox](https://www.virtualbox.org/) or [QEMU](https://www.qemu.org/), or in a browser with Fabian Hemmer's [v86 x86 emulator](https://github.com/copy/v86). 4 | 5 | This project also contains various bash scripts that help create/edit FreeDOS boot disk/sector image files. Details on those are provided below. 6 | 7 | # Demo 8 | 9 | A demo of one of the stripped down diskette images from this project running on [v86](https://github.com/copy/v86) is hosted [here](http://www.codercowboy.com/freedos/). 10 | 11 | Additionally, Fabian Hemmer hosts an excellent [v86 Demo](https://copy.sh/v86/) that demonstrates a number of OS installations such as versions of Windows, different Linux installations, and various DOS versions [here](https://copy.sh/v86/). 12 | 13 | # Boot Diskette Image Files 14 | 15 | FreeDOS Boot Diskette image files are available in the [bootdisks folder](https://github.com/codercowboy/freedosbootdisks/tree/master/bootdisks) of this project. 16 | 17 | The provided boot disk images are minimal. They only contain the following: [KERNEL.SYS](http://help.fdos.org/en/hhstndrd/base/kernel.htm), [CONFIG.SYS](http://help.fdos.org/en/hhstndrd/cnfigsys/index.htm), [AUTOEXEC.BAT](http://help.fdos.org/en/hhstndrd/batch/autoexec.htm), [COMMAND.COM](http://help.fdos.org/en/hhstndrd/base/command.htm), and a small [README.TXT](https://github.com/codercowboy/freedosbootdisks/blob/master/scripts/lib/boot_disk_contents/README.TXT) file with a link to this project. 18 | 19 | The boot disk images come in differing sizes (160K, 180K, 320K, 360K, 640K, 720K, 1200K, 1.4M) in case you need to fill the image with a few more programs or have a strange expected target disk size. 20 | 21 | **Note:** This project generates a 640K boot disk image. v86 does not support the 640K size. 22 | 23 | The provided images boot well in v86. I have not taken the time to see if they boot well on other virtualized platforms or on real vintage hardware. 24 | 25 | # Customizing Boot Disks 26 | 27 | To customize any of the provided boot disk images on MacOS, simply double click one of the boot diskette .img files in the Finder application to mount the disk, then use Finder (or the terminal, the disk will be mounted in /Volumes/FREEDOS) to customize the contents of the .img file. Be sure to eject the image file using Finder (or 'hditutil eject /Volumes/FREEDOS') when you've finished customizing it. 28 | 29 | # Advanced Boot Disk Customization 30 | 31 | The FreeDOS boot disks provided by this project were built with the [eddosboot.sh](https://github.com/codercowboy/freedosbootdisks/blob/master/scripts/eddosboot.sh) script, like so: 32 | 33 | ./eddosboot.sh CREATE_ALL_BOOT_DISKS 34 | 35 | When [eddosboot.sh](https://github.com/codercowboy/freedosbootdisks/blob/master/scripts/eddosboot.sh) creates boot disk images, the files from this project's [scripts/lib/boot_disk_contents](https://github.com/codercowboy/freedosbootdisks/tree/master/scripts/lib/boot_disk_contents) directory are copied to the diskette. 36 | 37 | If needed, you can customize the contents of the [scripts/lib/boot_disk_contents](https://github.com/codercowboy/freedosbootdisks/tree/master/scripts/lib/boot_disk_contents) directory and rebuild the boot disks again using the CREATE_ALL_BOOT_DISKS command shown above. 38 | 39 | The following resources will be helpful in customizing your installation: 40 | 41 | * [FreeDOS Reference](http://help.fdos.org/en/index.htm) 42 | * [FreeDOS CONFIG.SYS Reference](http://help.fdos.org/en/hhstndrd/cnfigsys/index.htm) 43 | * [FreeDOS COMMAND.COM Reference](http://help.fdos.org/en/hhstndrd/base/command.htm) 44 | * [FreeDOS AUTOEXEC.BAT Reference](http://help.fdos.org/en/hhstndrd/batch/autoexec.htm) 45 | * [FreeDOS HIMEM.EXE Reference](http://help.fdos.org/en/hhstndrd/base/himem.htm) 46 | * [FreeDOS NANSI.SYS Reference](http://help.fdos.org/en/hhstndrd/base/nansi.htm) 47 | * [FreeDOS chkdsk Reference](http://help.fdos.org/en/hhstndrd/base/chkdsk.htm) - Alternative to MS ScanDisk. 48 | * [FreeDOS fdisk Reference](http://help.fdos.org/en/hhstndrd/base/fdisk.htm) 49 | * [FreeDOS format Reference](http://help.fdos.org/en/hhstndrd/base/format.htm) 50 | * [FeeeDOS zip Reference](http://help.fdos.org/en/hhstndrd/util/zip.htm) 51 | * [FreeDOS unzip Reference](http://help.fdos.org/en/hhstndrd/util/unzip.htm) 52 | * [FreeDos md5sum Reference](http://help.fdos.org/en/hhstndrd/util/md5sum.htm) 53 | * [WinWorld's Dos Application Library](https://winworldpc.com/library/applications/platform-dos) - Contains useful retro software such as WordPerfect, compilers, pkzip, etc. 54 | * [v86 FreeDOS boot diskette image](https://github.com/copy/images/blob/master/freedos722.img) - Contains several additional utilities, drivers, and games that aren't found in boot disks provided by this project. 55 | 56 | If you don't feel comfortable customizing a FreeDOS boot disk's configuration by hand, then you can create FreeDOS boot diskettes by running through a virtualized FreeDOS installation using [QEMU](https://www.qemu.org/) or [VirtualBox](https://www.virtualbox.org/). Once you have the resulting FreeDOS boot disk image in hand, you can copy the disk's contents to the [scripts/lib/boot_disk_contents](https://github.com/codercowboy/freedosbootdisks/tree/master/scripts/lib/boot_disk_contents) directory and create the minimally sized disks again. 57 | 58 | * [FreeDOS on QEMU Installation Guide](http://how-to.wikia.com/wiki/How_to_install_FreeDOS_in_QEMU) 59 | * [Another FreeDOS QEMU Installation Guide](https://opensource.com/article/17/10/run-dos-applications-linux) 60 | 61 | # Boot Sectors 62 | 63 | [Boot Sectors](https://en.wikipedia.org/wiki/Boot_sector) for each of the FreeDOS .img files mentioned above have been extracted and placed are available in the [bootsectors folder](https://github.com/codercowboy/freedosbootdisks/tree/master/bootsectors) of this project. 64 | 65 | # Booting in v86 66 | 67 | If you're unfamiliar with [v86](https://github.com/copy/v86), it's a x86 javascript emulator that emulates a vintage PC in a browser. v86 provides hardware emulation of floppy disk drives, IDE hard disk drives, sound blaster 16, VGA, PCI and more. 68 | 69 | The author has various Linux, Windows, and DOS demo operating systems running on v86 on his personal host here: 70 | 71 | https://copy.sh/v86/ 72 | 73 | It took a while for me to figure out how to run just his FreeDOS demo image locally without the big demo that requires downloading multiple OS images, here's my source for that: 74 | 75 | 76 | 80 | 81 | 96 | 97 |
98 |
99 | 100 |
101 | 102 | A few notes on the sample shown above: 103 | 104 | * An expanded version of this sample.html file, complete with the seabios.img, vgabios.img, libv86.js, and freedos.boot.disk.160K.img are provided in the [sample](https://github.com/codercowboy/freedosbootdisks/tree/master/sample) directory of this project. 105 | * You won't be able to run the sample by simply opening the html file from disk in your browser. Instead, you will need to run a http webserver on your machine. The easiest way to run a server on your machine is to run the following python command in the directory you want to server the html and img files from: 106 | 107 | python -m SimpleHTTPServer 8070 108 | 109 | * The above example will host a [web server](https://en.wikipedia.org/wiki/Web_server) on your machine on port 8070. If you start the webserver in the [sample](https://github.com/codercowboy/freedosbootdisks/tree/master/sample) folder of this project, the url to fetch the sample.html will be: 110 | 111 | http://localhost:8070/sample.html 112 | 113 | * Other popular [web server](https://en.wikipedia.org/wiki/Web_server) options to consider are [Apache](https://httpd.apache.org/), [NGINX](https://www.nginx.com/), a [LAMP](https://en.wikipedia.org/wiki/LAMP_(software_bundle)) stack (which includes apache as the webserver portion of the stack), [Tomcat](http://tomcat.apache.org/), or [Geronimo](http://geronimo.apache.org/). More webserver options are listed [here](https://en.wikipedia.org/wiki/Comparison_of_web_server_software). 114 | * The seabios.bin and vgabios.bin images came from the v86 github project [here](https://github.com/copy/v86/tree/master/bios). 115 | * If you prefer, you can build the libv86.js file yourself by cloning the [v86 project](https://github.com/copy/v86) from github. And [building it](https://github.com/copy/v86#how-to-build-run-and-embed) yourself. 116 | * You can run a non-minimized js version of the v86 library locally if you clone the [v86 repo](https://github.com/copy/v86) and reference the v86 debug loader.js file from source like the [v86 source sample html](https://github.com/copy/v86/blob/master/debug.html) does. 117 | * You can easily provide more images for emulated hard drives and cdroms using the v86 api with params such as "hda" and "cdrom". The cd-rom images can be (or must be?) in .iso format. 118 | * The v86 API has a bunch of other options, those are documented [here](https://github.com/copy/v86/blob/master/docs/api.md) and [here](https://github.com/copy/v86). 119 | 120 | # Scripts 121 | 122 | A few scripts were written to automate boot disk creation, boot sector extraction/importing, and sector size/count editing. The scripts are in the [scripts](https://github.com/codercowboy/freedosbootdisks/tree/master/scripts) directory of this project. 123 | 124 | All scripts are bash scripts intended to run on MacOS. 125 | 126 | The primary script is [eddosboot.sh](https://github.com/codercowboy/freedosbootdisks/blob/master/scripts/eddosboot.sh). It provides the following operations: 127 | 128 | * Create minimal FreeDOS boot disk image files in the following sizes: 160K, 320K, 720K, 1.44M 129 | * Create FreeDOS boot sector image files for supported boot disk sizes. 130 | * Display boot disk / boot sector sector sizes and sector counts. 131 | * Change boot disk / boot sector sector sizes and sector counts. 132 | * Copy boot sectors from one image file to another. 133 | * Bulk mode to generate all supported boot disk sizes. 134 | * Bulk mode to generate all supported boot sectors. 135 | 136 | The script provides usage instructions when it's run without any arguments like so: 137 | 138 | ./eddosboot.sh 139 | 140 | The [testeddosboot.sh](https://github.com/codercowboy/freedosbootdisks/blob/master/scripts/testeddosboot.sh) script provides some unit tests that exercise [eddosboot.sh](https://github.com/codercowboy/freedosbootdisks/blob/master/scripts/eddosboot.sh) functionality. 141 | 142 | The project also includes a small library of hex conversion and read/write bash functions in [hexlib.sh](https://github.com/codercowboy/freedosbootdisks/blob/master/scripts/hexlib.sh). A test script [testhexlib.sh](https://github.com/codercowboy/freedosbootdisks/blob/master/scripts/testhexlib.sh) is also provided. 143 | 144 | # Bugs / Possible Problems 145 | 146 | I'm not a vintage hardware guru, so I would not be surprised if the images I've hacked together have issues in the boot sectors such as: 147 | 148 | * Sector sizes might be unrealistic for real diskettes. For example, all of the images and boot sectors here specify a sector size of 512 bytes. I have not done the research to figure out if a 160KB diskette had a different sector size than a 1.4MB diskette typically had. 149 | 150 | * Sectors Per Track / Sectors Per Cylinder specifications may be unrealistic for real diskettes. The provided boot sectors and images have left these values in the original state from the source image provided by the v86 project. 151 | 152 | If you want to edit sector sizes, sector counts, volume names, cylinder counts, or track counts, I recommend the following resources: 153 | 154 | * [Boot Records Reference - VERY good.](https://thestarman.pcministry.com/asm/mbr/index.html) 155 | * [MS Dos 5.0 Boot Sector Reference](https://thestarman.pcministry.com/asm/mbr/DOS50FDB.htm) 156 | * [PC Guide Floppy Disk Reference](http://www.pcguide.com/ref/fdd/formatSummary-c.html) 157 | * [David Anderson's Thorough Explanation of Bootable Floppy Disks](https://apple.stackexchange.com/a/338748/305123) 158 | * [Decimal To Hex / Hex to Decimal Converters](https://www.rapidtables.com/convert/number/decimal-to-hex.html?x=320) 159 | * [Hex Editor for MacOS](https://ridiculousfish.com/hexfiend/) 160 | 161 | # Resources 162 | 163 | Boot process resources: 164 | 165 | * [Boot Records Reference - VERY good.](https://thestarman.pcministry.com/asm/mbr/index.html) 166 | * [MS Dos 5.0 Boot Sector Reference](https://thestarman.pcministry.com/asm/mbr/DOS50FDB.htm) 167 | * [MBR and VBR Specifics](https://superuser.com/questions/1149657/mbr-and-vbr-specifics) 168 | * [PC Guide Floppy Disk Reference](http://www.pcguide.com/ref/fdd/formatSummary-c.html) 169 | * [David Anderson's Thorough Explanation of Bootable Floppy Disks](https://apple.stackexchange.com/a/338748/305123) 170 | * [Overview of MBR boot process](https://neosmart.net/wiki/mbr-boot-process/) 171 | * [MBR Fix Guide for Various Windows Versions](https://neosmart.net/wiki/fix-mbr/) 172 | * [More MBR Tools](https://thestarman.pcministry.com/asm/mbr/BootToolsRefs.htm) 173 | * [Boot Sector Tools for Windows](https://www.raymond.cc/blog/5-free-tools-to-backup-and-restore-master-boot-record-mbr/) 174 | * [Wikipedia's List Of Floppy Disk Formats](https://en.wikipedia.org/wiki/List_of_floppy_disk_formats) 175 | 176 | Open-source / Free DOS distributions: 177 | 178 | * [DOSBox](https://www.dosbox.com/) 179 | * [FreeDOS](http://www.freedos.org/) 180 | * [MS-DOS 1.25 & 2.0](https://github.com/Microsoft/MS-DOS) 181 | 182 | Tools: 183 | 184 | * [FreeDOS](http://www.freedos.org/) 185 | * [VirtualBox](https://www.virtualbox.org/) - Free OS virtualization platform. 186 | * [QEMU](https://www.qemu.org/) - Another free OS virtualization platform. 187 | * [Win World](https://winworldpc.com/home) - Old OS (Windows 3.1, 9x, Dos, and more) installation files and old software (Turbo Pascal, WordStar, etc) 188 | * [Old Version](http://www.oldversion.com/) - Archive of many old versions for various retro and current software such as WinAmp, FireFox, and more. 189 | 190 | Javascript x86 Emulation: 191 | 192 | * [v86](https://github.com/copy/v86) 193 | * [js-dos](https://js-dos.com/) - x86 javascript emulator tailored for converting and running dos games in browser. 194 | * [em-dosbox](https://github.com/dreamlayers/em-dosbox) 195 | * [asm.js](http://asmjs.org/) 196 | * [WebAssembly](https://webassembly.org/) 197 | * [emscripten](https://github.com/kripken/emscripten) - LLVM (C/C++) to JS compiler 198 | 199 | Further Resources: 200 | 201 | * [v86 image creation tips for QEMU](https://github.com/copy/v86/issues/128) 202 | * [Gentle Introduction to FreeDOS](https://opensource.com/article/18/4/gentle-introduction-freedos) 203 | * [FreeDOS on QEMU Installation Guide](http://how-to.wikia.com/wiki/How_to_install_FreeDOS_in_QEMU) 204 | * [Another FreeDOS QEMU Installation Guide](https://opensource.com/article/17/10/run-dos-applications-linux) 205 | * [Booting QEMU from a Floppy Image](https://stackoverflow.com/questions/19961095/os-development-booting-from-floppy-drive-using-qemu) 206 | * [Creating A Minimal Boot Sector For v86](https://blog.benjdoherty.com/2017/08/07/Writing-a-minimal-boot-sector-for-the-v86-emulator/) 207 | * [archive.org's free dos game library](https://archive.org/details/softwarelibrary_msdos_games?) - powered by em-dosbox 208 | 209 | # Trivia 210 | 211 | While building this project, I learned a lot about bootable diskettes. It was not trivial to piece together how a vintage bootable diskette image can be created on modern hardware, or how the boot process works in general. I'm providing these bits of trivia and details in hopes that it will help others looking for understanding: 212 | 213 | A bootable hard drive has several parts to it. The very first sector on the disk is called a [boot sector](https://en.wikipedia.org/wiki/Boot_sector). The boot sector is 512 bytes long and contains the [Master Boot Record](https://en.wikipedia.org/wiki/Master_boot_record) (aka MBR). The drive itself contains one or more [partitions](https://en.wikipedia.org/wiki/Disk_partitioning), which is a section of the drive that is mapped to a logical drive on your computer. A drive can have multiple partitions on it, but there's usually just one partition. 214 | 215 | When you create a [file system](https://en.wikipedia.org/wiki/File_system) on a disk by formatting a partition on the drive with tools such as MacOs' Disk Utility, the tools will ask you how large you want a partition to be. For example, you could create a 50GB partition and a 150GB partition on a 200GB drive. 216 | 217 | Consumer laptops often ship with a drive that has multiple partitions on it, the first being a read-only "[recovery partition](https://computers.tutsplus.com/tutorials/the-os-x-recovery-partition-what-it-is-why-its-there-and-how-to-remove-it--mac-31796)" that's used to reinstall the OS, and the second being the main partition used to house the OS and your files. 218 | 219 | When a machine is dual-bootable, there can either be two (or more) physical hard disks in the system with one partition per drive, or two partitions on a single drive. [Boot Camp](https://en.wikipedia.org/wiki/Boot_Camp_(software) for MacOS does just this, it creates a second partition on your hard drive and formats with a filesystem format that Windows understands (such as [ExFAT](https://en.wikipedia.org/wiki/ExFAT)), while keeping the primary partition on the drive formatted in [APFS](https://en.wikipedia.org/wiki/Apple_File_System) or some other format that MacOS recognizes and boots from. 220 | 221 | When a machine starts, one of the partitions on the primary drive is marked as 'active', meaning that's the partition for the BIOS to jump to and start loading the OS from. Boot managers that help with dual booting a machine into multiple operating systems simply switch which partition is marked as active, then boots the machine to that partition (I think.. maybe the boot manager is actually on a third partition and the third partition is always marked as active, with the boot manager program tricking the OS into booting from another partition when the user selects which OS they want to boot). 222 | 223 | When the computer boots, or a new drive is attached to the computer, partitions are mapped to [logical drives](https://en.wikipedia.org/wiki/Logical_disk), such as a "C:" or "D:" drive on a Windows Machine. On linux/MacOS systems the drive's partitions will be mapped to filesystem abstractions such as /dev/disk1s1 and /dev/disk1s2. For MacOS terminal fans, the logical volume versions of the the partitions will also be mounted under the /Volumes directory, for example: /Volumes/MYDRIVE. 224 | 225 | When an external drive, cdrom, usb stick, or sd card is plugged into a machine, the drive will popup in Finder (on Macos) or Explorer (on Windows) with the volume labels such as MYDRIVE mentioned above. Under the covers on a linux or MacOS system, the OS is automatically doing two operations to make the volume available: attaching and mounting the drive. 226 | 227 | When a drive is attached but not mounted, the drive can be fully erased, reformatted, or byte-for-byte copied to another disk or an image file using the unix [dd](http://man7.org/linux/man-pages/man1/dd.1.html) command. The dd program differs from [cp](http://man7.org/linux/man-pages/man1/cp.1.html) in that it copies every single byte from the disk, meaning it will copy or erase every sector from the disk, including boot sectors, partition information, [FAT](https://en.wikipedia.org/wiki/File_Allocation_Table) information, empty space, every file and folder in their current state (including their exact fragmentation across different sectors on disk, and even 'deleted' file data on the disk where the file has merely been removed from the FAT but the bytes of the file are not securely erased by writing zeros or random data over the file's contents on disk). The dd command is often used when attempting to recover a faulty or failing disk that's mounting incorrectly or has a corrupted FAT. 228 | 229 | The [df](https://linux.die.net/man/1/df) command on Linux and MacOS machines can be used to view information about the attached and mounted disks in your system. In this example below, I provide the -h switch to the df command, so the command prints out the drive capacity and free space in a human-legible summarized format such as 1GB rather than 1073741824 bytes: 230 | 231 | jbmbpro2014:dist jason$ df -h 232 | 233 | Filesystem Size Used Avail Capacity iused ifree %iused Mounted on 234 | /dev/disk1s1 234Gi 192Gi 39Gi 84% 1633783 9223372036853142024 0% / 235 | /dev/disk1s4 234Gi 2.0Gi 39Gi 5% 2 9223372036854775805 0% /private/var/vm 236 | /dev/disk1s3 234Gi 495Mi 39Gi 2% 14 9223372036854775793 0% /Volumes/Recovery 237 | 238 | 239 | The [dd](http://man7.org/linux/man-pages/man1/dd.1.html) command can also be used to create an empty zeroed-out .img file like so: 240 | 241 | dd if=/dev/zero of=myimage.img bs=512 count=1440 242 | 243 | With the example above, we're specify that the .img file is filled with zeroes (copied from /dev/zero, which when read will always return zeros). The created .img file has sectors that are 512 bytes in size, and it has 1440 sectors. A kilobyte is 1024 bytes, so two sectors form a kilobyte. When we divide 1440 by 2, we get 720 - so a 1440 sector 512 byte per sector disk is 720KB, which is one common disk size for floppy disks. 244 | 245 | Early [floppy disks came in sizes](https://en.wikipedia.org/wiki/Floppy_disk#Sizes) of 160KB and later disks regularly came in a 1.44MB size. v86 supports a few common floppy disk sizes, those are found in the [floppy.js](https://github.com/copy/v86/blob/master/src/floppy.js) file: 246 | 247 | var floppy_types = { 248 | 160 : { type: 1, tracks: 40, sectors: 8 , heads: 1 }, 249 | 180 : { type: 1, tracks: 40, sectors: 9 , heads: 1 }, 250 | 200 : { type: 1, tracks: 40, sectors: 10, heads: 1 }, 251 | 320 : { type: 1, tracks: 40, sectors: 8 , heads: 2 }, 252 | 360 : { type: 1, tracks: 40, sectors: 9 , heads: 2 }, 253 | 400 : { type: 1, tracks: 40, sectors: 10, heads: 2 }, 254 | 720 : { type: 3, tracks: 80, sectors: 9 , heads: 2 }, 255 | 1200 : { type: 2, tracks: 80, sectors: 15, heads: 2 }, 256 | 1440 : { type: 4, tracks: 80, sectors: 18, heads: 2 }, 257 | 1722 : { type: 5, tracks: 82, sectors: 21, heads: 2 }, 258 | 2880 : { type: 5, tracks: 80, sectors: 36, heads: 2 }, 259 | }; 260 | 261 | **Note:** This project generates a 640K boot disk image. v86 does not support the 640K size. 262 | 263 | More details on floppy disk formats are listed on [Wikipedia's List Of Floppy Disk Formats](https://en.wikipedia.org/wiki/List_of_floppy_disk_formats). 264 | 265 | A floppy diskette does not have a MBR, but instead has a [Volume Boot Record](https://en.wikipedia.org/wiki/Volume_boot_record) (VBR). I'm a little confused on the difference between a MBR and a VBR, but my basic understanding is that a MBR is used on devices like hard disks that support partitions or multiple partitions, and a VBR is used on storage mediums without partitions (such as floppy diskettes). 266 | 267 | The bootable FreeDOS diskettes provided in this project are [FAT12](https://en.wikipedia.org/wiki/File_Allocation_Table#FAT12) format, because that's what the original v86 floppy image was formatted in. I think later boot disk formats for Windows, Linux, and other operating systems were not necessarily FAT12, as the MBR/VBR generally has a jump command that points to some x86 instructions to first run a disk driver, which is a program that reads FAT information from a drive and controls organizing, reading, and writing files and folders. After the disk driver is started up, it transfers command to a boot file on the disk such as CONFIG.SYS in FreeDOS, which then continues booting the OS. 268 | 269 | There are a number of other useful commands for image creation, partitioning, and formatting in Linux/MacOS that can be used in a terminal: 270 | 271 | * [Managing Linux Partitions With fdisk](https://www.tecmint.com/fdisk-commands-to-manage-linux-disk-partitions/) 272 | * [Another fdisk Reference](https://www.linkedin.com/pulse/how-create-partition-using-fdisk-man-linux-sanjay-kumar/) 273 | * [newfs_msdos](https://www.freebsd.org/cgi/man.cgi?query=newfs_msdos&apropos=0&sektion=0&manpath=FreeBSD+5.2-RELEASE&format=html) 274 | * [dd](http://man7.org/linux/man-pages/man1/dd.1.html) 275 | * [Using dd to save/restore a boot sector](https://unix.stackexchange.com/questions/252509/using-dd-in-order-to-save-and-restore-a-boot-sector) 276 | * [df](https://linux.die.net/man/1/df) 277 | * [hdiutil](https://ss64.com/osx/hdiutil.html) - MacOS only 278 | * [Disk Utility](https://en.wikipedia.org/wiki/Disk_Utility) and the terminal version [diskutil](https://ss64.com/osx/diskutil.html) - MacOS only 279 | 280 | This is all my very high-level novice understanding of how MBRs, VBRs, boot sectors, partitions, and file system formats work. There are a number of resources listed above that go into much greater detail, with much greater authority than I possess. In particular, be sure to check out [Boot Records Revealed](https://thestarman.pcministry.com/asm/mbr/index.html) with extremely detailed information about the byte-level breakdown of various boot sector formats. 281 | 282 | Note that there's more trivia and gotchas document inside the script files contained within this project. 283 | 284 | # Purpose 285 | 286 | These images were created while working on a [book](http://www.happyacro.com) about vintage computing and the insanity associated with a software engineering career. While writing the book, emulated operating systems in a browser were in vogue, and I wanted to create a nostalgic browser-based DOS experience to advertise the book. I found the [v86 library](https://github.com/copy/v86). The sample FreeDOS image provided with v86 is a 720KB diskette that includes a few programs and tools that I was not interested in providing on my book's site, so I went on a quest to strip the diskette image file down in size. In that quest, I sought a way to recreate a bootable diskette with an arbitrary size via a script that would not require manually clicking through a FreeDOS installation wizard or changing the original source diskette image, and I realized there weren't any incredibly straight forward resources for creating a minimal bootable FreeDOS diskette image, so here we are. 287 | 288 | # Credit 289 | 290 | * Thanks to Fabian Hemmer for [v86](https://github.com/copy/v86) and his original [FreeDOS diskette image](https://github.com/copy/images/blob/master/freedos722.img) that I used to seed this project's images. 291 | * Thanks to [David Anderson](https://apple.stackexchange.com/users/107222/david-anderson) for helping me understand the difference between MBR and VBR, and providing example code to extract the boot sector from one image and stick it into another in [this Stack Overflow thread](https://apple.stackexchange.com/questions/338718/creating-bootable-freedos-dos-floppy-diskette-img-file-for-v86-on-osx). 292 | * [MS Dos 5.0 Boot Sector Reference](https://thestarman.pcministry.com/asm/mbr/DOS50FDB.htm) 293 | * [FreeDOS](http://www.freedos.org/) 294 | * The [Hex Fiend](https://ridiculousfish.com/hexfiend/) hex editor for MacOS was used to verify and troubleshoot this project's boot sectors. 295 | 296 | # Contributing 297 | 298 | If you'd like to contribute to the project, feel free to send me PRs, I'll credit you for your additions. 299 | 300 | Some suggested future improvements: 301 | 302 | * More boot sector display/edit property support for properties such as the boot sector volume label, head count, cylinder count, etc. 303 | * Make the scripts cross-portable, rather than MacOS specific. 304 | * Improve the baseline CONFIG.SYS file. 305 | * Documentation improvements. 306 | * Productize hexlib.sh to be a nice standalone script rather than just bash functions. 307 | * Add more supported boot disk image sizes (all possible variations are listed in 'man newfs_msdos'). In particular, I could use help figuring out the newfs_msdos incantation for a 2.88MB image. 308 | * Add error handling when a disk is being created and the user's boot_disk_contents files overflow the disk size. 309 | * Add more error checking in general, checking for exit codes from various commands. 310 | 311 | # License 312 | 313 | All V86 assets, including the copied [FreeDOS image file](https://github.com/codercowboy/freedosbootdisks/blob/master/scripts/lib/v86.freedos.boot.disk.img), the [vgabios.img](https://github.com/codercowboy/freedosbootdisks/blob/master/sample/vgabios.bin), the [seabios.img](https://github.com/codercowboy/freedosbootdisks/blob/master/sample/seabios.bin), and the compiled [libv86.js](https://github.com/codercowboy/freedosbootdisks/blob/master/sample/libv86.js) file in this repository are copyrighted by Fabian Hemmer or other respective owners. License information for those assets is available on the [v86 licensing terms page](https://github.com/copy/v86). 314 | 315 | All FreeDOS assets, including the [KERNEL.SYS](https://github.com/codercowboy/freedosbootdisks/blob/master/scripts/lib/boot_disk_contents/KERNEL.SYS) and [COMMAND.COM](https://github.com/codercowboy/freedosbootdisks/blob/master/scripts/lib/boot_disk_contents/COMMAND.COM) FreeDOS files are licensed as described [here](http://wiki.freedos.org/wiki/index.php/Open_source_software). 316 | 317 | All scripts are licensed with the [Apache license](http://en.wikipedia.org/wiki/Apache_license), which is a great license because, essentially it: 318 | 319 | * a) covers liability - my code should work, but I'm not liable if you do something stupid with it 320 | * b) allows you to copy, fork, and use the code, even commercially 321 | * c) is [non-viral](http://en.wikipedia.org/wiki/Viral_license), that is, your derivative code doesn't *have to be* open source to use it 322 | 323 | Other great licensing options for your own code: [BSD License](https://en.wikipedia.org/wiki/BSD_licenses), [MIT License](https://en.wikipedia.org/wiki/MIT_License), or [Creative Commons](https://en.wikipedia.org/wiki/Creative_Commons_license). 324 | 325 | Here's the license: 326 | 327 | Copyright (c) 2018, Coder Cowboy, LLC. All rights reserved. 328 | 329 | Redistribution and use in source and binary forms, with or without 330 | modification, are permitted provided that the following conditions are met: 331 | 332 | 1. Redistributions of source code must retain the above copyright notice, this 333 | list of conditions and the following disclaimer. 334 | 335 | 2. Redistributions in binary form must reproduce the above copyright notice, 336 | this list of conditions and the following disclaimer in the documentation 337 | and/or other materials provided with the distribution. 338 | 339 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 340 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 341 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 342 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 343 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 344 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 345 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 346 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 347 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 348 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 349 | 350 | The views and conclusions contained in the software and documentation are those 351 | of the authors and should not be interpreted as representing official policies, 352 | either expressed or implied. 353 | -------------------------------------------------------------------------------- /bootdisks/freedos.boot.disk.1.4MB.img: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codercowboy/freedosbootdisks/330e522bf9323ad54a6ff68c9b7cb9ae7a084cb4/bootdisks/freedos.boot.disk.1.4MB.img -------------------------------------------------------------------------------- /bootdisks/freedos.boot.disk.1200K.img: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codercowboy/freedosbootdisks/330e522bf9323ad54a6ff68c9b7cb9ae7a084cb4/bootdisks/freedos.boot.disk.1200K.img -------------------------------------------------------------------------------- /bootdisks/freedos.boot.disk.160K.img: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codercowboy/freedosbootdisks/330e522bf9323ad54a6ff68c9b7cb9ae7a084cb4/bootdisks/freedos.boot.disk.160K.img -------------------------------------------------------------------------------- /bootdisks/freedos.boot.disk.180K.img: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codercowboy/freedosbootdisks/330e522bf9323ad54a6ff68c9b7cb9ae7a084cb4/bootdisks/freedos.boot.disk.180K.img -------------------------------------------------------------------------------- /bootdisks/freedos.boot.disk.320K.img: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codercowboy/freedosbootdisks/330e522bf9323ad54a6ff68c9b7cb9ae7a084cb4/bootdisks/freedos.boot.disk.320K.img -------------------------------------------------------------------------------- /bootdisks/freedos.boot.disk.360K.img: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codercowboy/freedosbootdisks/330e522bf9323ad54a6ff68c9b7cb9ae7a084cb4/bootdisks/freedos.boot.disk.360K.img -------------------------------------------------------------------------------- /bootdisks/freedos.boot.disk.640K.img: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codercowboy/freedosbootdisks/330e522bf9323ad54a6ff68c9b7cb9ae7a084cb4/bootdisks/freedos.boot.disk.640K.img -------------------------------------------------------------------------------- /bootdisks/freedos.boot.disk.720K.img: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codercowboy/freedosbootdisks/330e522bf9323ad54a6ff68c9b7cb9ae7a084cb4/bootdisks/freedos.boot.disk.720K.img -------------------------------------------------------------------------------- /bootsectors/freedos.boot.sector.1.4MB.img: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codercowboy/freedosbootdisks/330e522bf9323ad54a6ff68c9b7cb9ae7a084cb4/bootsectors/freedos.boot.sector.1.4MB.img -------------------------------------------------------------------------------- /bootsectors/freedos.boot.sector.1200K.img: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codercowboy/freedosbootdisks/330e522bf9323ad54a6ff68c9b7cb9ae7a084cb4/bootsectors/freedos.boot.sector.1200K.img -------------------------------------------------------------------------------- /bootsectors/freedos.boot.sector.160K.img: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codercowboy/freedosbootdisks/330e522bf9323ad54a6ff68c9b7cb9ae7a084cb4/bootsectors/freedos.boot.sector.160K.img -------------------------------------------------------------------------------- /bootsectors/freedos.boot.sector.180K.img: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codercowboy/freedosbootdisks/330e522bf9323ad54a6ff68c9b7cb9ae7a084cb4/bootsectors/freedos.boot.sector.180K.img -------------------------------------------------------------------------------- /bootsectors/freedos.boot.sector.320K.img: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codercowboy/freedosbootdisks/330e522bf9323ad54a6ff68c9b7cb9ae7a084cb4/bootsectors/freedos.boot.sector.320K.img -------------------------------------------------------------------------------- /bootsectors/freedos.boot.sector.360K.img: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codercowboy/freedosbootdisks/330e522bf9323ad54a6ff68c9b7cb9ae7a084cb4/bootsectors/freedos.boot.sector.360K.img -------------------------------------------------------------------------------- /bootsectors/freedos.boot.sector.640K.img: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codercowboy/freedosbootdisks/330e522bf9323ad54a6ff68c9b7cb9ae7a084cb4/bootsectors/freedos.boot.sector.640K.img -------------------------------------------------------------------------------- /bootsectors/freedos.boot.sector.720K.img: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codercowboy/freedosbootdisks/330e522bf9323ad54a6ff68c9b7cb9ae7a084cb4/bootsectors/freedos.boot.sector.720K.img -------------------------------------------------------------------------------- /sample/freedos.boot.disk.160K.img: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codercowboy/freedosbootdisks/330e522bf9323ad54a6ff68c9b7cb9ae7a084cb4/sample/freedos.boot.disk.160K.img -------------------------------------------------------------------------------- /sample/sample.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | FreeDOS Boot Disk Sample 5 | 12 | 13 | 38 | 39 | 40 |
41 |
42 | 43 |
44 | 45 |
46 |

This FreeDOS browser example is powered by v86. This specific sample was created for the FreeDOS Boot Disks project.

47 |
48 | 49 | -------------------------------------------------------------------------------- /sample/seabios.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codercowboy/freedosbootdisks/330e522bf9323ad54a6ff68c9b7cb9ae7a084cb4/sample/seabios.bin -------------------------------------------------------------------------------- /sample/vgabios.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codercowboy/freedosbootdisks/330e522bf9323ad54a6ff68c9b7cb9ae7a084cb4/sample/vgabios.bin -------------------------------------------------------------------------------- /scripts/eddosboot.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ################################################################################# 4 | # 5 | # eddosboot.sh - FreeDOS boot disk/sector image creation utilities 6 | # 7 | # written by Jason Baker (jason@onejasonforsale.com) 8 | # project's github: https://github.com/codercowboy/freedosbootdisks 9 | # more info: http://www.codercowboy.com 10 | # 11 | ################################################################################# 12 | # 13 | # UPDATES: 14 | # 15 | # 2018/10/19 16 | # - Remove MacOS dot files from created disk 17 | # - Add support for 180K, 360K, 640K, 1200K disk sizes 18 | # 19 | # 2018/10/15 20 | # - Initial version 21 | # 22 | ################################################################################# 23 | # 24 | # Copyright (c) 2018, Coder Cowboy, LLC. All rights reserved. 25 | # 26 | # Redistribution and use in source and binary forms, with or without 27 | # modification, are permitted provided that the following conditions are met: 28 | # 29 | # 1. Redistributions of source code must retain the above copyright notice, this 30 | # list of conditions and the following disclaimer. 31 | # 32 | # 2. Redistributions in binary form must reproduce the above copyright notice, 33 | # this list of conditions and the following disclaimer in the documentation 34 | # and/or other materials provided with the distribution. 35 | # 36 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 37 | # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 38 | # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 39 | # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 40 | # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 41 | # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 42 | # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 43 | # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 44 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 45 | # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 46 | # 47 | # The views and conclusions contained in the software and documentation are those 48 | # of the authors and should not be interpreted as representing official policies, 49 | # either expressed or implied. 50 | # 51 | ################################################################################# 52 | 53 | print_usage() { 54 | echo "" 55 | echo "eddosboot - MacOS tools for managing minimal FreeDOS boot disk image files" 56 | echo " written by Jason Baker (jason@codercowboy.com), 2018" 57 | echo "" 58 | echo "USAGE: eddosboot [COMMAND] [FILE]" 59 | echo "" 60 | echo "Commands:" 61 | echo "" 62 | echo " The following commands create a minimal FreeDOS boot disk in the specified file in .img format." 63 | echo " The disk will be FAT12 formatted. The disk will contain FreeDOS KERNEL.SYS, CONFIG.SYS, and COMMAND.COM files." 64 | echo "" 65 | echo " CREATE BOOT_DISK [VOLUME LABEL] [FILE] - creates a 1.4MB FreeDOS boot disk" 66 | echo " CREATE BOOT_DISK [VOLUME LABEL] [SECTOR SIZE] [SECTOR COUNT] [FILE] - creates boot disk w/ given sector specifications" 67 | echo " CREATE BOOT_DISK [VOLUME LABEL] [SIZE] [FILE] - creates a boot disk with specified file size" 68 | echo " Supported boot disk file sizes: 1.4MB, 1200K, 720K, 640K, 360K, 320K, 180K, and 160K." 69 | echo " CREATE_ALL_BOOT_DISKS - create all supported boot disks in build/bootdisks folder." 70 | echo " CREATE_ALL_BOOT_DISKS [VOLUME LABEL] - create all supported boot disks in build/bootdisks folder with specified Volume Label." 71 | echo "" 72 | echo " Example Usage: CREATE_BOOT_DISK MYDISK 720K disk.img" 73 | echo "" 74 | echo " Example above would create a 720K FreeDOS boot disk in the disk.img file with the volume label of MYDISK." 75 | echo "" 76 | echo "---" 77 | echo "" 78 | echo " The following commands create 512 byte FreeDOS boot sectors in specified file in .img format." 79 | echo " If specified file exists, first 512 bytes of file will be overwritten with new boot record." 80 | echo " If specified file is new, newly created file will be 512 bytes and contain boot sector." 81 | echo "" 82 | echo " CREATE BOOT_SECTOR [FILE] - creates a 1.4MB FreeDOS .img boot sector." 83 | echo " CREATE BOOT_SECTOR [SECTOR SIZE] [SECTOR COUNT] [FILE] - create boot sector with given sector specifications" 84 | echo " CREATE BOOT_SECTOR [SIZE] [FILE] - create boot sector with specified standard diskette size" 85 | echo " Supported boot disk sizes: 1.4MB, 1200K, 720K, 640K, 360K, 320K, 180K, and 160K." 86 | echo " CREATE_ALL_BOOT_SECTORS - create all supported boot sectors in build/bootsectors folder." 87 | echo "" 88 | echo "---" 89 | echo "" 90 | echo " COPY_BOOT_SECTOR [SOURCE FILE] [TARGET FILE] - copy boot sector from source file to target file, overwritting target's boot sector if target exists" 91 | echo "" 92 | echo "---" 93 | echo "" 94 | echo " SHOW ALL [FILE] - displays all boot record properties for specified file" 95 | echo " SHOW SECTOR_SIZE [FILE] - display sector size" 96 | echo " SHOW SECTOR_COUNT [FILE] - display sector count" 97 | echo "" 98 | echo "---" 99 | echo "" 100 | echo " CHANGE SECTOR_SIZE [SIZE] [FILE] - changes file's boot record sector size to specified size in bytes" 101 | echo " CHANGE SECTOR_COUNT [COUNT] [FILE] - change file's boot record sector count" 102 | echo "" 103 | if [ ! -z "${1}" ]; then 104 | echo "" 105 | echo "ERROR: ${1}" 106 | exit 1 107 | fi 108 | } 109 | 110 | # changes a boot sector property 111 | # arg 1: mode: SECTOR_SIZE or SECTOR_COUNT 112 | # arg 2: value to write 113 | # arg 3: boot sector file 114 | change_boot_sector_property() { 115 | # from: https://thestarman.pcministry.com/asm/mbr/DOS50FDB.htm 116 | # sector size: 0x0B-0x0C (2 bytes) 117 | # sector count: 0x13-0x14 (2 bytes) 118 | debug_log "change_boot_sector_property mode: ${1}, value: ${2}, file: ${3}" 119 | HEX_BYTES=$(convert_number_to_hex "${2}") 120 | debug_log "change_boot_sector_property value hex bytes: ${HEX_BYTES}" 121 | # if only one byte is in number ie 0x01, change it to 0x0001 122 | if [ ${#HEX_BYTES} -eq 4 ]; then 123 | HEX_BYTES=`echo -n ${HEX_BYTES} | sed 's/0x/0x00/'` 124 | debug_log "change_boot_sector_property value hex bytes after padding: ${HEX_BYTES}" 125 | fi 126 | HEX_BYTES_REVERSED=$(reverse_hex_order "${HEX_BYTES}") 127 | debug_log "change_boot_sector_property value hex bytes reversed: ${HEX_BYTES_REVERSED}" 128 | DECIMAL_ADDRESS="" 129 | if [ "SECTOR_SIZE" = "${1}" ]; then 130 | DECIMAL_ADDRESS=$(convert_hex_to_number "0x0B") 131 | debug_log "change_boot_sector_property sector size write address '${DECIMAL_ADDRESS} (converted from '0x0B')" 132 | elif [ "SECTOR_COUNT" = "${1}" ]; then 133 | DECIMAL_ADDRESS=$(convert_hex_to_number "0x13") 134 | debug_log "change_boot_sector_property sector count write address '${DECIMAL_ADDRESS} (converted from '0x13')" 135 | else 136 | print_usage "Unsupported 'CHANGE' mode: ${ACTION}" 137 | fi 138 | debug_log "change_boot_sector_property writing value: ${HEX_BYTES_REVERSED} to address: ${DECIMAL_ADDRESS} in file: ${3}" 139 | replace_bytes "${DECIMAL_ADDRESS}" "${HEX_BYTES_REVERSED}" "${3}" 140 | } 141 | 142 | SCRIPT_HOME="`dirname ${BASH_SOURCE[0]}`" 143 | BUILD_HOME="${SCRIPT_HOME}/../build" 144 | SOURCE_BOOT_DISK="${SCRIPT_HOME}/lib/v86.freedos.boot.disk.img" 145 | 146 | if [ "DEBUG" = "${1}" ]; then 147 | DEBUG_HEXLIB="true" 148 | shift 149 | fi 150 | 151 | if [ ! -f "${SCRIPT_HOME}/hexlib.sh" ]; then 152 | print_usage "Cannot find hexlib.sh, should be in path: ${SCRIPT_HOME}/hexlib.sh" 153 | fi 154 | 155 | source "${SCRIPT_HOME}/hexlib.sh" 156 | 157 | debug_log "SCRIPT_HOME: ${SCRIPT_HOME}" 158 | debug_log "Arguments: ${@}" 159 | 160 | if [ -z "${1}" -o "HELP" = "${1}" ]; then 161 | print_usage; 162 | exit 1 163 | fi 164 | 165 | OPERATION="${1}" 166 | debug_log "OPERATION: ${OPERATION}" 167 | shift 168 | 169 | ACTION="${1}" 170 | debug_log "ACTION: ${ACTION}" 171 | shift 172 | 173 | if [ "SHOW" = "${OPERATION}" ]; then 174 | FILE="${1}" 175 | if [ -z "${FILE}" ]; then 176 | print_usage "Invalid file: ${FILE}" 177 | elif [ ! -r "${FILE}" ]; then 178 | print_usage "Invalid file. It's not a file or isn't readable: ${FILE}" 179 | fi 180 | 181 | debug_log "Mode: SHOW, file: ${FILE}" 182 | 183 | # from: https://thestarman.pcministry.com/asm/mbr/DOS50FDB.htm 184 | # sector size: 0x0B-0x0C (2 bytes) 185 | # sector count: 0x13-0x14 (2 bytes) 186 | 187 | debug_log "Mode SHOW extracting sector size (this is always fetched in show mode)" 188 | DECIMAL_ADDRESS=$(convert_hex_to_number "0x0B") 189 | SECTOR_SIZE=`extract_reversed_number_from_file "${DECIMAL_ADDRESS}" 2 "${FILE}"` 190 | debug_log "Mode SHOW extracting sector count (this is always fetched in show mode)" 191 | DECIMAL_ADDRESS=$(convert_hex_to_number "0x13") 192 | SECTOR_COUNT=`extract_reversed_number_from_file "${DECIMAL_ADDRESS}" 2 "${FILE}"` 193 | 194 | if [ "ALL" = "${ACTION}" ]; then 195 | echo "Boot properties for file: ${FILE}" 196 | echo " Sector size: ${SECTOR_SIZE}" 197 | echo " Sector count: ${SECTOR_COUNT}" 198 | elif [ "SECTOR_SIZE" = "${ACTION}" ]; then 199 | echo -n "${SECTOR_SIZE}" 200 | elif [ "SECTOR_COUNT" = "${ACTION}" ]; then 201 | echo -n "${SECTOR_COUNT}" 202 | elif [ "VOLUME_LABEL" = "${ACTION}" ]; then 203 | echo -n "${VOLUME_LABEL}" 204 | else 205 | print_usage "Unsupported 'SHOW' mode: ${ACTION}" 206 | fi 207 | elif [ "CHANGE" = "${OPERATION}" ]; then 208 | VALUE="${1}" 209 | if [ -z "${VALUE}" ]; then 210 | print_usage "Invalid 'CHANGE' mode value: ${VALUE}" 211 | fi 212 | shift 213 | 214 | FILE="${1}" 215 | if [ -z "${FILE}" ]; then 216 | print_usage "Invalid file: ${FILE}" 217 | elif [ ! -w "${FILE}" ]; then 218 | print_usage "Invalid file. It's not a file or isn't writable: ${FILE}" 219 | fi 220 | 221 | debug_log "Mode: CHANGE, value: ${VALUE}, file: ${FILE}" 222 | change_boot_sector_property "${ACTION}" "${VALUE}" "${FILE}" 223 | elif [ "CREATE" = "${OPERATION}" ]; then 224 | if [ ! -f "${SOURCE_BOOT_DISK}" ]; then 225 | echo "ERROR: source FreeDOS boot disk image is missing: ${SOURCE_BOOT_DISK}" 226 | exit 1 227 | fi 228 | 229 | VOLUME_LABEL=""; 230 | if [ "BOOT_DISK" = "${ACTION}" ]; then 231 | VOLUME_LABEL="${1}" 232 | if [ -z "${VOLUME_LABEL}" ]; then #TODO: check for valid volume label here too 233 | print_usage "Invalid volume label: ${VOLUME_LABEL}" 234 | fi 235 | shift 236 | fi 237 | 238 | FORMAT=1440 239 | FILE_SIZE="1.4MB" 240 | SECTOR_SIZE="512" 241 | SECTOR_COUNT="" 242 | FILE="" 243 | if [ ! -z "${3}" ]; then #if there are three arguments, it's [SECTOR COUNT] [SECTOR SIZE] [FILE] 244 | if [ -z "${2}" -o -z "${1}" ]; then 245 | print_usage "Invalid 'CREATE' operation arguments: ${@}" 246 | fi 247 | FILE="${3}" 248 | SECTOR_COUNT="${2}" 249 | SECTOR_SIZE="${1}" 250 | elif [ ! -z "${2}" ]; then #if there are two arguments it's [SIZE] [FILE] 251 | if [ -z "${1}" ]; then 252 | print_usage "Invalid 'CREATE' operation arguments: ${@}" 253 | fi 254 | FILE="${2}" 255 | FILE_SIZE="${1}" 256 | elif [ ! -z "${1}" ]; then #if there's only one argument it's [FILE] 257 | FILE="${1}" 258 | else 259 | print_usage "Invalid 'CREATE' operation arguments: ${@}" 260 | fi 261 | 262 | # more formats are listed here: https://en.wikipedia.org/wiki/List_of_floppy_disk_formats 263 | # the newfs_msdos command's man page (man newfs_msdos) lists a few more supported file sizes too 264 | 265 | if [ "1.4MB" = "${FILE_SIZE}" ]; then 266 | FORMAT=1440 267 | elif [ "1200K" = "${FILE_SIZE}" ]; then 268 | FORMAT=1200 269 | elif [ "720K" = "${FILE_SIZE}" ]; then 270 | FORMAT=720 271 | elif [ "640K" = "${FILE_SIZE}" ]; then 272 | FORMAT=640 273 | elif [ "360K" = "${FILE_SIZE}" ]; then 274 | FORMAT=360 275 | elif [ "320K" = "${FILE_SIZE}" ]; then 276 | FORMAT=320 277 | elif [ "180K" = "${FILE_SIZE}" ]; then 278 | FORMAT=180 279 | elif [ "160K" = "${FILE_SIZE}" ]; then 280 | FORMAT=160 281 | else 282 | print_usage "Unsupported 'CREATE' mode file size: '${FILE_SIZE}', supported sizes are: 1.4MB, 1200K, 720K, 640K, 360K, 320K, 180K, and 160K." 283 | fi 284 | 285 | SECTOR_COUNT=$((FORMAT * 2)) 286 | 287 | # copy the source v86 boot sector to a tmp file 288 | debug_log "Creating temp boot sector: ${TMP_BOOT_SECTOR}" 289 | mkdir -p "${BUILD_HOME}" 290 | TMP_BOOT_SECTOR="${BUILD_HOME}/bootsector.tmp" 291 | dd if="${SOURCE_BOOT_DISK}" of="${TMP_BOOT_SECTOR}" bs=512 count=1 292 | 293 | #fix the sector size and count in the boot sector 294 | change_boot_sector_property SECTOR_SIZE "${SECTOR_SIZE}" "${TMP_BOOT_SECTOR}" 295 | change_boot_sector_property SECTOR_COUNT "${SECTOR_COUNT}" "${TMP_BOOT_SECTOR}" 296 | 297 | # NOTE: probable bug here, we're not setting correct cylinder/head count on various formats 298 | # see: https://en.wikipedia.org/wiki/List_of_floppy_disk_formats 299 | 300 | # from: https://apple.stackexchange.com/questions/338718/creating-bootable-freedos-dos-floppy-diskette-img-file-for-v86-on-osx 301 | if [ "BOOT_DISK" = "${ACTION}" ]; then 302 | echo "Creating ${FILE_SIZE} FreeDOS boot disk with ${SECTOR_COUNT} sectors, sector size is ${SECTOR_SIZE}, file: ${FILE}" 303 | 304 | # create an empty img file with all zeros in it 305 | dd if=/dev/zero of="${FILE}" bs=${SECTOR_SIZE} count=${SECTOR_COUNT} 306 | 307 | # format the floppy image as FAT12 308 | newfs_msdos -B "${TMP_BOOT_SECTOR}" -v "${VOLUME_LABEL}" -f ${FORMAT} -b 1024 -S ${SECTOR_SIZE} -r 1 -F 12 "${FILE}" 309 | 310 | # mount our target .img file we just created, it'll mount as /Volumes/${VOLUME_LABEL}, copy our minimal files to it 311 | echo "Copying boot disk contents from ${SCRIPT_HOME}/lib/boot_disk_contents" 312 | hdiutil attach "${FILE}" 313 | cp -r "${SCRIPT_HOME}/lib/boot_disk_contents/" "/Volumes/${VOLUME_LABEL}" 314 | # remove dot files 315 | find "/Volumes/${VOLUME_LABEL}" -name "._*" -delete 316 | rm -Rf "/Volumes/${VOLUME_LABEL}/.fseventsd/" 317 | hdiutil eject "/Volumes/${VOLUME_LABEL}/" 318 | 319 | echo "Finished creating boot diskette image: ${FILE}" 320 | 321 | elif [ "BOOT_SECTOR" = "${ACTION}" ]; then 322 | echo "Creating ${FILE_SIZE} FreeDOS boot sector with ${SECTOR_COUNT} sectors, sector size is ${SECTOR_SIZE}, file: ${FILE}" 323 | cp "${TMP_BOOT_SECTOR}" "${FILE}" 324 | else 325 | rm "${TMP_BOOT_SECTOR}" 326 | print_usage "Unsupported 'CREATE' operation: ${ACTION}, supported operations are BOOT_DISK and BOOT_SECTOR" 327 | fi 328 | rm "${TMP_BOOT_SECTOR}" 329 | elif [ "COPY_BOOT_SECTOR" = "${OPERATION}" ]; then 330 | SOURCE_FILE="${ACTION}" 331 | if [ -z "${SOURCE_FILE}" ]; then 332 | print_usage "Invalid source file: ${SOURCE_FILE}" 333 | elif [ ! -r "${SOURCE_FILE}" ]; then 334 | print_usage "Invalid source file. It's not a file or isn't readable: ${SOURCE_FILE}" 335 | fi 336 | TARGET_FILE="${1}" 337 | if [ -z "${TARGET_FILE}" ]; then 338 | print_usage "Invalid target file: ${TARGET_FILE}" 339 | elif [ -f "${TARGET_FILE}" -a ! -w "${SOURCE_FILE}" ]; then 340 | print_usage "Invalid target file. It's not a file or isn't writable: ${TARGET_FILE}" 341 | fi 342 | debug_log "Mode: COPY_BOOT_SECTOR, source file: ${SOURCE_FILE}, target file: ${TARGET_FILE}" 343 | 344 | dd if="${SOURCE_FILE}" of="${TARGET_FILE}" bs=512 count=1 conv=notrunc 345 | elif [ "CREATE_ALL_BOOT_DISKS" = "${OPERATION}" ]; then 346 | VOLUME_LABEL="FREEDOS"; 347 | if [ ! -z "${ACTION}" ]; then 348 | VOLUME_LABEL="${ACTION}" 349 | fi 350 | BUILD_FOLDER="${BUILD_HOME}/bootdisks" 351 | mkdir -p "${BUILD_FOLDER}" 352 | echo "Creating standard FreeDOS boot disks in folder: ${BUILD_FOLDER}" 353 | 354 | FILE="${BUILD_FOLDER}/freedos.boot.disk.1.4MB.img" 355 | echo "Creating 1.4MB FreeDOS boot disk with volume label '${VOLUME_LABEL}': ${FILE}" 356 | "${SCRIPT_HOME}/eddosboot.sh" CREATE BOOT_DISK "${VOLUME_LABEL}" 1.4MB "${FILE}" 357 | 358 | FILE="${BUILD_FOLDER}/freedos.boot.disk.1200K.img" 359 | echo "Creating 1200K FreeDOS boot disk with volume label '${VOLUME_LABEL}': ${FILE}" 360 | "${SCRIPT_HOME}/eddosboot.sh" CREATE BOOT_DISK "${VOLUME_LABEL}" 1200K "${FILE}" 361 | 362 | FILE="${BUILD_FOLDER}/freedos.boot.disk.720K.img" 363 | echo "Creating 720K FreeDOS boot disk with volume label '${VOLUME_LABEL}': ${FILE}" 364 | "${SCRIPT_HOME}/eddosboot.sh" CREATE BOOT_DISK "${VOLUME_LABEL}" 720K "${FILE}" 365 | 366 | FILE="${BUILD_FOLDER}/freedos.boot.disk.640K.img" 367 | echo "Creating 640K FreeDOS boot disk with volume label '${VOLUME_LABEL}': ${FILE}" 368 | "${SCRIPT_HOME}/eddosboot.sh" CREATE BOOT_DISK "${VOLUME_LABEL}" 640K "${FILE}" 369 | 370 | FILE="${BUILD_FOLDER}/freedos.boot.disk.360K.img" 371 | echo "Creating 360K FreeDOS boot disk with volume label '${VOLUME_LABEL}': ${FILE}" 372 | "${SCRIPT_HOME}/eddosboot.sh" CREATE BOOT_DISK "${VOLUME_LABEL}" 360K "${FILE}" 373 | 374 | FILE="${BUILD_FOLDER}/freedos.boot.disk.320K.img" 375 | echo "Creating 320K FreeDOS boot disk with volume label '${VOLUME_LABEL}': ${FILE}" 376 | "${SCRIPT_HOME}/eddosboot.sh" CREATE BOOT_DISK "${VOLUME_LABEL}" 320K "${FILE}" 377 | 378 | FILE="${BUILD_FOLDER}/freedos.boot.disk.180K.img" 379 | echo "Creating 180K FreeDOS boot disk with volume label '${VOLUME_LABEL}': ${FILE}" 380 | "${SCRIPT_HOME}/eddosboot.sh" CREATE BOOT_DISK "${VOLUME_LABEL}" 180K "${FILE}" 381 | 382 | FILE="${BUILD_FOLDER}/freedos.boot.disk.160K.img" 383 | echo "Creating 160K FreeDOS boot disk with volume label '${VOLUME_LABEL}': ${FILE}" 384 | "${SCRIPT_HOME}/eddosboot.sh" CREATE BOOT_DISK "${VOLUME_LABEL}" 160K "${FILE}" 385 | 386 | echo "Finished creating standard FreeDOS boot disks." 387 | elif [ "CREATE_ALL_BOOT_SECTORS" = "${OPERATION}" ]; then 388 | BUILD_FOLDER="${BUILD_HOME}/bootsectors" 389 | mkdir -p "${BUILD_FOLDER}" 390 | 391 | echo "Creating standard FreeDOS boot sectors in folder: ${BUILD_FOLDER}" 392 | 393 | FILE="${BUILD_FOLDER}/freedos.boot.sector.1.4MB.img" 394 | echo "Creating 1.4M FreeDOS boot sector: ${FILE}" 395 | "${SCRIPT_HOME}/eddosboot.sh" CREATE BOOT_SECTOR 1.4MB "${FILE}" 396 | 397 | FILE="${BUILD_FOLDER}/freedos.boot.sector.1200K.img" 398 | echo "Creating 1200K FreeDOS boot sector: ${FILE}" 399 | "${SCRIPT_HOME}/eddosboot.sh" CREATE BOOT_SECTOR 1200K "${FILE}" 400 | 401 | FILE="${BUILD_FOLDER}/freedos.boot.sector.720K.img" 402 | echo "Creating 720K FreeDOS boot sector: ${FILE}" 403 | "${SCRIPT_HOME}/eddosboot.sh" CREATE BOOT_SECTOR 720K "${FILE}" 404 | 405 | FILE="${BUILD_FOLDER}/freedos.boot.sector.640K.img" 406 | echo "Creating 640K FreeDOS boot sector: ${FILE}" 407 | "${SCRIPT_HOME}/eddosboot.sh" CREATE BOOT_SECTOR 640K "${FILE}" 408 | 409 | FILE="${BUILD_FOLDER}/freedos.boot.sector.360K.img" 410 | echo "Creating 360K FreeDOS boot sector: ${FILE}" 411 | "${SCRIPT_HOME}/eddosboot.sh" CREATE BOOT_SECTOR 360K "${FILE}" 412 | 413 | FILE="${BUILD_FOLDER}/freedos.boot.sector.320K.img" 414 | echo "Creating 320K FreeDOS boot sector: ${FILE}" 415 | "${SCRIPT_HOME}/eddosboot.sh" CREATE BOOT_SECTOR 320K "${FILE}" 416 | 417 | FILE="${BUILD_FOLDER}/freedos.boot.sector.180K.img" 418 | echo "Creating 180K FreeDOS boot sector: ${FILE}" 419 | "${SCRIPT_HOME}/eddosboot.sh" CREATE BOOT_SECTOR 180K "${FILE}" 420 | 421 | FILE="${BUILD_FOLDER}/freedos.boot.sector.160K.img" 422 | echo "Creating 160K FreeDOS boot sector: ${FILE}" 423 | "${SCRIPT_HOME}/eddosboot.sh" CREATE BOOT_SECTOR 160K "${FILE}" 424 | 425 | echo "Finished creating standard FreeDOS boot sectors." 426 | else 427 | print_usage "Unsupported operation: ${OPERATION}" 428 | fi 429 | -------------------------------------------------------------------------------- /scripts/hexlib.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ################################################################################# 4 | # 5 | # hexlib.sh - bash utilities to work with extracting / writing binary data 6 | # 7 | # written by Jason Baker (jason@onejasonforsale.com) 8 | # project's github: https://github.com/codercowboy/freedosbootdisks 9 | # more info: http://www.codercowboy.com 10 | # 11 | ################################################################################# 12 | # 13 | # UPDATES: 14 | # 15 | # 2018/10/15 16 | # - Initial version 17 | # 18 | ################################################################################# 19 | # 20 | # Copyright (c) 2018, Coder Cowboy, LLC. All rights reserved. 21 | # 22 | # Redistribution and use in source and binary forms, with or without 23 | # modification, are permitted provided that the following conditions are met: 24 | # 25 | # 1. Redistributions of source code must retain the above copyright notice, this 26 | # list of conditions and the following disclaimer. 27 | # 28 | # 2. Redistributions in binary form must reproduce the above copyright notice, 29 | # this list of conditions and the following disclaimer in the documentation 30 | # and/or other materials provided with the distribution. 31 | # 32 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 33 | # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 34 | # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 35 | # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 36 | # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 37 | # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 38 | # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 39 | # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 40 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 41 | # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 42 | # 43 | # The views and conclusions contained in the software and documentation are those 44 | # of the authors and should not be interpreted as representing official policies, 45 | # either expressed or implied. 46 | # 47 | ################################################################################# 48 | 49 | debug_log() { 50 | if [ "true" = "${DEBUG_HEXLIB}" ]; then 51 | echo "DEBUG: ${1}" > /dev/stderr 52 | fi 53 | } 54 | 55 | # verifies test results 56 | # arg 1: test name 57 | # arg 2: expected result 58 | # arg 3: actual result 59 | # returns: nothing 60 | verify_test() { 61 | if [ ! "${2}" = "${3}" ]; then 62 | echo "TEST FAILURE: ${1}, expected: '${2}', actual: '${3}'" 63 | exit 1 64 | else 65 | echo "Test SUCCESS: ${1}, expected: '${2}', actual: '${3}'" 66 | fi 67 | } 68 | 69 | # reverses a hex string such as "0x4241" to "0x4142" 70 | # arg 1: string to reverse 71 | # returns: reversed string 72 | reverse_hex_order() { 73 | debug_log "reverse_hex_order input: ${1}" 74 | # input is something like "0x434241", strip the "0x" from front 75 | INPUT=`echo -n "${1}" | sed 's/0x//'` 76 | #debug_log "reverse_hex_order input with '0x' stripped from front: ${INPUT}" 77 | # inptu is now 434241 78 | # put a space between each pair so we have 43 42 41 79 | INPUT=`echo -n "${INPUT}" | sed 's/\(..\)/\1 /g'` 80 | #debug_log "reverse_hex_order input with space between each pair: ${INPUT}" 81 | # input is now something like 43 42 41, put them together in reverse order 82 | OUTPUT="" 83 | for PAIR in ${INPUT}; do 84 | #debug_log "reverse_hex_order current pair: '${PAIR}'" 85 | PAIR=`echo -n "${PAIR}" | sed 's/ //g'` #remove spaces from end of pair 86 | if [ ! -z "${PAIR}" ]; then #only prepend non-empty pairs 87 | OUTPUT="${PAIR}${OUTPUT}" 88 | fi 89 | done 90 | # now output is something like 434241, add "0x before it" 91 | OUTPUT=`echo -n "0x${OUTPUT}"` 92 | # now output is 0x434241 93 | debug_log "reverse_hex_order result: ${OUTPUT}" 94 | echo -n "${OUTPUT}" 95 | } 96 | 97 | # extracts bytes from file from specified offset in a hex string format 98 | # arg 1: byte offset to start reading from in decimal ie "123" 99 | # arg 2: count of bytes to read in decimal ie "4" 100 | # arg 3: file to extract from 101 | # returns: bytes in hex format ie "0xABCD" 102 | extract_bytes() { 103 | debug_log "extract_bytes offset: ${1}, byte count: ${2}, file: ${3}" 104 | # from: https://unix.stackexchange.com/questions/155085/fetching-individual-bytes-from-a-binary-file-into-a-variable-with-bash 105 | # and: https://stackoverflow.com/questions/6292645/convert-binary-data-to-hex-in-shell-script 106 | OUTPUT="0x`dd if="${3}" count=${2} bs=1 skip=${1} conv=notrunc | hexdump -e '"%X"'`" 107 | OUTPUT=$(fix_hex_padding "${OUTPUT}") 108 | # extracted bytes are backwards hex like 434241 when we want 414243 109 | OUTPUT=`reverse_hex_order "${OUTPUT}"` 110 | # extracted bytes are now 0x414243 111 | debug_log "extract_bytes extracted: ${OUTPUT}" 112 | echo -n "${OUTPUT}" 113 | } 114 | 115 | # replace bytes to file at specified offset 116 | # arg 1: byte offset to start writing to in decimal ie "123" 117 | # arg 2: bytes to write in hex string format ie "0xABCD" 118 | # arg 3: file to replace bytes in 119 | # returns: nothing 120 | replace_bytes() { 121 | debug_log "replace_bytes offset: ${1}, bytes to write: ${2}, file: ${3}" 122 | # from: https://stackoverflow.com/questions/4783657/cli-write-byte-at-address-hexedit-modify-binary-from-the-command-line 123 | # input is something like "0x434241", strip the "0x" from front 124 | INPUT=`echo -n "${2}" | sed 's/0x//'` 125 | # byte count to write is length of string / 2 126 | BYTE_COUNT=`expr ${#INPUT} / 2` 127 | # printf needs a format of \x41\x42 with "\x" between each hex pair to print hex as ascii 128 | # put the "\x" in the string 129 | INPUT=`echo -n "${INPUT}" | sed 's/\(..\)/\\\\x\1/g'` 130 | debug_log "replace_bytes final input: ${INPUT}, byte count: ${BYTE_COUNT}" 131 | printf ${INPUT} | dd of="${3}" bs=1 seek=${1} count=${BYTE_COUNT} conv=notrunc 132 | } 133 | 134 | # converts hex string to a decimal number 135 | # arg 1: hex string to convert ie "0xABCD" 136 | # returns: decimal number such as "123" 137 | convert_hex_to_number() { 138 | debug_log "convert_hex_to_number input: ${1}" 139 | # from: https://stackoverflow.com/questions/378829/convert-decimal-to-hexadecimal-in-unix-shell-script 140 | # input is something like "0x0FFF", convert it to a number: 141 | NUMBER=`echo $((${1}))` 142 | debug_log "convert_hex_to_number result: ${NUMBER}" 143 | echo -n "${NUMBER}" 144 | } 145 | 146 | # converts decimal number to a hex string 147 | # arg 1: decimal number such as "123" 148 | # returns: hex string ie "0xABCD" 149 | convert_number_to_hex() { 150 | debug_log "convert_number_to_hex input: ${1}" 151 | # from: https://stackoverflow.com/questions/378829/convert-decimal-to-hexadecimal-in-unix-shell-script 152 | # and: http://wiki.bash-hackers.org/commands/builtin/printf 153 | # input example: 12 154 | RESULT=`printf "%X" "${1}"` 155 | # result is now "C", we want to zero pad this to be "0C" if there's an odd number of digits 156 | RESULT=$(fix_hex_padding "0x${RESULT}") 157 | RESULT=`echo -n "${RESULT}" | sed 's/0x//'` # strip 0x off front: 158 | debug_log "convert_number_to_hex initial hex: ${RESULT}" 159 | REMAINDER=`expr ${#RESULT} % 2` 160 | debug_log "convert_number_to_hex remainder: ${REMAINDER}" 161 | if [ ${REMAINDER} -eq 1 -o "0" = "${RESULT}" ]; then 162 | # odd number of hex digits, add a zero at front 163 | RESULT="0${RESULT}" 164 | fi 165 | # add "0x" to beginning of result 166 | RESULT="0x${RESULT}" 167 | debug_log "convert_number_to_hex result: ${RESULT}" 168 | echo -n "${RESULT}" 169 | } 170 | 171 | # adds an extra "0" to the beginning of a hex string that has an odd number of characters in it, ie "0xF" -> "0x0F" 172 | # arg 1: hex string to pad, ie "0xF" 173 | # returns: padded hex string, ie "0x0F" 174 | fix_hex_padding() { 175 | debug_log "fix_hex_padding fixing input: ${1}" 176 | RESULT=`echo -n "${1}" | sed 's/0x//'` # strip 0x off front: 177 | # from: https://stackoverflow.com/questions/17368067/length-of-string-in-bash 178 | # and: http://tldp.org/LDP/abs/html/ops.html 179 | REMAINDER=`expr ${#RESULT} % 2` 180 | if [ ${REMAINDER} -eq 1 -o "0" = "${RESULT}" ]; then 181 | # odd number of hex digits, add a zero at front 182 | RESULT="0${RESULT}" 183 | fi 184 | RESULT="0x${RESULT}" 185 | debug_log "fix_hex_padding result: ${RESULT}" 186 | echo -n "${RESULT}" 187 | } 188 | 189 | # converts hex string to an ascii string 190 | # arg 1: hex string to convert ie "0xABCD" 191 | # returns: ascii string such as "Jason" 192 | convert_hex_to_ascii_string() { 193 | debug_log "convert_hex_to_ascii_string input: ${1}" 194 | # from: https://stackoverflow.com/questions/13160309/conversion-hex-string-into-ascii-in-bash-command-line 195 | # input is like 0x424141 196 | INPUT=`echo -n "${1}" | sed 's/0x//'` # strip 0x off front: 197 | # now input is 424141 198 | # echo needs a format of \x41\x42 with "\x" between each hex pair to print hex as ascii 199 | # put the "\x" in the string 200 | INPUT=`echo -n "${INPUT}" | sed 's/\(..\)/\\\\x\1/g'` 201 | debug_log "convert_hex_to_ascii_string input with '\x' between each pair: ${INPUT}" 202 | # now input is \x42\x41\x41 203 | RESULT=`echo -n -e "${INPUT}"` 204 | debug_log "convert_hex_to_ascii_string result: ${RESULT}" 205 | # now result is BAA 206 | echo -n "${RESULT}" 207 | } 208 | 209 | # converts ascii string to a hex string 210 | # arg 1: ascii string such as "Jason" 211 | # returns: hex string ie "0xABCD" 212 | convert_ascii_string_to_hex() { 213 | debug_log "convert_ascii_string_to_hex input: ${1}" 214 | # from: https://stackoverflow.com/questions/5724761/ascii-hex-convert-in-bash/5725125 215 | RESULT="0x`echo -n "${1}" | hexdump -e '/1 "%02X"'`" 216 | debug_log "convert_ascii_string_to_hex result: ${RESULT}" 217 | echo -n "${RESULT}" 218 | } 219 | 220 | 221 | # extracts a decimal number from bytes in a file 222 | # arg 1: byte offset to start reading from in decimal ie "123" 223 | # arg 2: length of bytes to read 224 | # arg 3: file to extract from 225 | # returns: decimal number such as "123" 226 | extract_number_from_file() { 227 | debug_log "extract_number_from_file offset: ${1}, bytes to read: ${2}, file: ${3}" 228 | HEX_BYTES=$(extract_bytes ${1} ${2} "${3}") 229 | NUMBER=$(convert_hex_to_number ${HEX_BYTES}) 230 | debug_log "extract_number_from_file result: ${NUMBER}" 231 | echo -n "${NUMBER}" 232 | } 233 | 234 | # extracts a decimal number from bytes in a file where hex bytes in file are reversed (ie should be 0x021A but are read as 0x1A02) 235 | # arg 1: byte offset to start reading from in decimal ie "123" 236 | # arg 2: length of bytes to read 237 | # arg 3: file to extract from 238 | # returns: decimal number such as "123" 239 | extract_reversed_number_from_file() { 240 | debug_log "extract_reversed_number_from_file offset: ${1}, bytes to read: ${2}, file: ${3}" 241 | HEX_BYTES=$(extract_bytes ${1} ${2} "${3}") 242 | HEX_BYTES_REVERSED=$(reverse_hex_order "${HEX_BYTES}") 243 | NUMBER=$(convert_hex_to_number ${HEX_BYTES_REVERSED}) 244 | debug_log "extract_number_from_file result: ${NUMBER}" 245 | echo -n "${NUMBER}" 246 | } 247 | 248 | 249 | # extracts a ascii string from bytes in a file 250 | # arg 1: byte offset to start reading from in decimal ie "123" 251 | # arg 2: length of bytes to read 252 | # arg 3: file to extract from 253 | # returns: ascii string such as "Jason" 254 | extract_string_from_file() { 255 | debug_log "extract_string_from_file offset: ${1}, bytes to read: ${2}, file: ${3}" 256 | HEX_BYTES=$(extract_bytes ${1} ${2} "${3}") 257 | ASCII_STRING=$(convert_hex_to_ascii_string ${HEX_BYTES}) 258 | debug_log "extract_string_from_file result: ${ASCII_STRING}" 259 | echo -n "${ASCII_STRING}" 260 | } 261 | 262 | # replaces the given number in a file 263 | # arg 1: byte offset to start writing to in decimal ie "123" 264 | # arg 2: number to write in decimal ie "123" 265 | # arg 3: file to write to 266 | # returns: nothing 267 | replace_number_in_file() { 268 | debug_log "replace_number_in_file offset: ${1}, number to write: ${2}, file: ${3}" 269 | HEX_BYTES=$(convert_number_to_hex "${2}") 270 | replace_bytes ${1} "${HEX_BYTES}" "${3}" 271 | } 272 | 273 | # replaces the given number in a file with reversed hex bytes written to disk 274 | # arg 1: byte offset to start writing to in decimal ie "123" 275 | # arg 2: number to write in decimal ie "123" 276 | # arg 3: file to write to 277 | # returns: nothing 278 | replace_reversed_number_in_file() { 279 | debug_log "replace_reversed_number_in_file offset: ${1}, number to write: ${2}, file: ${3}" 280 | HEX_BYTES=$(convert_number_to_hex "${2}") 281 | HEX_BYTES_REVERSED=$(reverse_hex_order "${HEX_BYTES}") 282 | replace_bytes ${1} "${HEX_BYTES_REVERSED}" "${3}" 283 | } 284 | 285 | 286 | # replaces the given string in a file 287 | # arg 1: byte offset to start writing to in decimal ie "123" 288 | # arg 2: ascii string to write ie "Jason" 289 | # arg 3: file to write to 290 | # returns: nothing 291 | replace_string_in_file() { 292 | debug_log "replace_string_in_file offset: ${1}, string to write: ${2}, file: ${3}" 293 | HEX_BYTES=$(convert_ascii_string_to_hex "${2}") 294 | replace_bytes ${1} "${HEX_BYTES}" "${3}" 295 | } -------------------------------------------------------------------------------- /scripts/lib/boot_disk_contents/AUTOEXEC.BAT: -------------------------------------------------------------------------------- 1 | ECHO OFF 2 | 3 | REM NOTE: If you remove this file from your boot disks, 4 | REM the FreeDOS boot will automaticall prompt user for date/time 5 | REM That issue can be fixed by adding the "/D" flag in CONFIG.SYS 6 | REM to the COMMAND.COM line , but /D will also make FreeDOS skip 7 | REM execution of AUTOEXEC.BAT. 8 | REM More info is here: 9 | REM https://sourceforge.net/p/freedos/mailman/message/5156181/ 10 | 11 | cls -------------------------------------------------------------------------------- /scripts/lib/boot_disk_contents/COMMAND.COM: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codercowboy/freedosbootdisks/330e522bf9323ad54a6ff68c9b7cb9ae7a084cb4/scripts/lib/boot_disk_contents/COMMAND.COM -------------------------------------------------------------------------------- /scripts/lib/boot_disk_contents/CONFIG.SYS: -------------------------------------------------------------------------------- 1 | SWITCHES=/N 2 | DOS=HIGH 3 | ;DEVICE=\FDOS\HIMEM.EXE /VERBOSE 4 | ;?DEVICE=\FDOS\EMM386.EXE /VERBOSE 5 | ;?DEVICE=\UMBPCI.SYS 6 | FILES=20 7 | BUFFERS=20 8 | SHELL=A:\COMMAND.COM /E:512 /MSG /P 9 | ;SHELLHIGH=\COMMAND.COM /E:256 /P 10 | -------------------------------------------------------------------------------- /scripts/lib/boot_disk_contents/KERNEL.SYS: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codercowboy/freedosbootdisks/330e522bf9323ad54a6ff68c9b7cb9ae7a084cb4/scripts/lib/boot_disk_contents/KERNEL.SYS -------------------------------------------------------------------------------- /scripts/lib/boot_disk_contents/README.TXT: -------------------------------------------------------------------------------- 1 | This FreeDOS boot diskette was created by Jason Baker for the FreeDOS Boot Disks project: 2 | 3 | https://github.com/codercowboy/freedosbootdisks 4 | 5 | Consult the project page linked above for details on software licensing. 6 | 7 | -------------------------------------------------------------------------------- /scripts/lib/v86.freedos.boot.disk.img: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codercowboy/freedosbootdisks/330e522bf9323ad54a6ff68c9b7cb9ae7a084cb4/scripts/lib/v86.freedos.boot.disk.img -------------------------------------------------------------------------------- /scripts/testeddosboot.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ################################################################################# 4 | # 5 | # testeddosboot.sh - Test suite for eddosboot.sh 6 | # 7 | # written by Jason Baker (jason@onejasonforsale.com) 8 | # project's github: https://github.com/codercowboy/freedosbootdisks 9 | # more info: http://www.codercowboy.com 10 | # 11 | ################################################################################# 12 | # 13 | # UPDATES: 14 | # 15 | # 2018/10/15 16 | # - Initial version 17 | # 18 | ################################################################################# 19 | # 20 | # Copyright (c) 2018, Coder Cowboy, LLC. All rights reserved. 21 | # 22 | # Redistribution and use in source and binary forms, with or without 23 | # modification, are permitted provided that the following conditions are met: 24 | # 25 | # 1. Redistributions of source code must retain the above copyright notice, this 26 | # list of conditions and the following disclaimer. 27 | # 28 | # 2. Redistributions in binary form must reproduce the above copyright notice, 29 | # this list of conditions and the following disclaimer in the documentation 30 | # and/or other materials provided with the distribution. 31 | # 32 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 33 | # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 34 | # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 35 | # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 36 | # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 37 | # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 38 | # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 39 | # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 40 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 41 | # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 42 | # 43 | # The views and conclusions contained in the software and documentation are those 44 | # of the authors and should not be interpreted as representing official policies, 45 | # either expressed or implied. 46 | # 47 | ################################################################################# 48 | 49 | DEBUG_HEXLIB="true" 50 | 51 | SCRIPT_HOME="`dirname ${BASH_SOURCE[0]}`" 52 | 53 | source "${SCRIPT_HOME}/hexlib.sh" 54 | 55 | SOURCE_BOOT_DISK="${SCRIPT_HOME}/lib/v86.freedos.boot.disk.img" 56 | BUILD_HOME="${SCRIPT_HOME}/../build" 57 | mkdir -p "${BUILD_HOME}" 58 | TEST_BOOT_SECTOR="${BUILD_HOME}/test.boot.sector.img" 59 | TEST_BOOT_DISK="${BUILD_HOME}/test.boot.disk.img" 60 | 61 | debug_log "SOURCE_BOOT_DISK: ${SOURCE_BOOT_DISK}" 62 | debug_log "TEST_BOOT_SECTOR: ${TEST_BOOT_SECTOR}" 63 | debug_log "TEST_BOOT_DISK: ${TEST_BOOT_DISK}" 64 | 65 | if [ -f "${TEST_BOOT_SECTOR}" ]; then 66 | rm "${TEST_BOOT_DISK}" 67 | fi 68 | 69 | if [ -f "${TEST_BOOT_SECTOR}" ]; then 70 | rm "${TEST_BOOT_SECTOR}" 71 | fi 72 | 73 | if [ ! -f "${SOURCE_BOOT_DISK}" ]; then 74 | echo "ERROR: source freedos boot disk image is missing: ${SOURCE_BOOT_DISK}" 75 | exit 1 76 | fi 77 | 78 | RESULT=$(${SCRIPT_HOME}/eddosboot.sh DEBUG SHOW SECTOR_SIZE "${SOURCE_BOOT_DISK}") 79 | verify_test "Test 1.a" "512" "${RESULT}" 80 | 81 | RESULT=$(${SCRIPT_HOME}/eddosboot.sh DEBUG SHOW SECTOR_COUNT "${SOURCE_BOOT_DISK}") 82 | verify_test "Test 1.b" "1440" "${RESULT}" 83 | 84 | # test boot sector extraction 85 | ${SCRIPT_HOME}/eddosboot.sh DEBUG COPY_BOOT_SECTOR "${SOURCE_BOOT_DISK}" "${TEST_BOOT_SECTOR}" 86 | if [ ! -f "${TEST_BOOT_SECTOR}" ]; then 87 | echo "Test 2.a failure, test disk wasn't copied: ${TEST_BOOT_SECTOR}" 88 | exit 1 89 | fi 90 | echo "Test 2.a SUCCESS: test boot sector was copied." 91 | # from: https://unix.stackexchange.com/questions/16640/how-can-i-get-the-size-of-a-file-in-a-bash-script 92 | FILE_SIZE=$(stat -f%z "${TEST_BOOT_SECTOR}") 93 | if [ ! "512" = "${FILE_SIZE}" ]; then 94 | echo "Test 2.b failure, test boot sector size isn't 512 bytes, it's: ${FILE_SIZE}" 95 | exit 1 96 | fi 97 | echo "Test 2.b SUCCESS: test boot sector is 512 bytes." 98 | RESULT=$(${SCRIPT_HOME}/eddosboot.sh DEBUG SHOW SECTOR_SIZE "${TEST_BOOT_SECTOR}") 99 | verify_test "Test 2.c" "512" "${RESULT}" 100 | RESULT=$(${SCRIPT_HOME}/eddosboot.sh DEBUG SHOW SECTOR_COUNT "${TEST_BOOT_SECTOR}") 101 | verify_test "Test 2.d" "1440" "${RESULT}" 102 | 103 | # test changing sector info on test boot sector 104 | ${SCRIPT_HOME}/eddosboot.sh DEBUG CHANGE SECTOR_SIZE 512 "${TEST_BOOT_SECTOR}" 105 | RESULT=$(${SCRIPT_HOME}/eddosboot.sh DEBUG SHOW SECTOR_SIZE "${TEST_BOOT_SECTOR}") 106 | verify_test "Test 3.a" "512" "${RESULT}" 107 | 108 | ${SCRIPT_HOME}/eddosboot.sh DEBUG CHANGE SECTOR_SIZE 1024 "${TEST_BOOT_SECTOR}" 109 | RESULT=$(${SCRIPT_HOME}/eddosboot.sh DEBUG SHOW SECTOR_SIZE "${TEST_BOOT_SECTOR}") 110 | verify_test "Test 3.b" "1024" "${RESULT}" 111 | 112 | ${SCRIPT_HOME}/eddosboot.sh DEBUG CHANGE SECTOR_SIZE 1 "${TEST_BOOT_SECTOR}" 113 | RESULT=$(${SCRIPT_HOME}/eddosboot.sh DEBUG SHOW SECTOR_SIZE "${TEST_BOOT_SECTOR}") 114 | verify_test "Test 3.c" "1" "${RESULT}" 115 | 116 | ${SCRIPT_HOME}/eddosboot.sh DEBUG CHANGE SECTOR_SIZE 512 "${TEST_BOOT_SECTOR}" 117 | RESULT=$(${SCRIPT_HOME}/eddosboot.sh DEBUG SHOW SECTOR_SIZE "${TEST_BOOT_SECTOR}") 118 | verify_test "Test 3.d" "512" "${RESULT}" 119 | 120 | ${SCRIPT_HOME}/eddosboot.sh DEBUG CHANGE SECTOR_SIZE 19 "${TEST_BOOT_SECTOR}" 121 | RESULT=$(${SCRIPT_HOME}/eddosboot.sh DEBUG SHOW SECTOR_SIZE "${TEST_BOOT_SECTOR}") 122 | verify_test "Test 3.e" "19" "${RESULT}" 123 | 124 | ${SCRIPT_HOME}/eddosboot.sh DEBUG CHANGE SECTOR_COUNT 1200 "${TEST_BOOT_SECTOR}" 125 | RESULT=$(${SCRIPT_HOME}/eddosboot.sh DEBUG SHOW SECTOR_COUNT "${TEST_BOOT_SECTOR}") 126 | verify_test "Test 4.a" "1200" "${RESULT}" 127 | 128 | ${SCRIPT_HOME}/eddosboot.sh DEBUG CHANGE SECTOR_COUNT 5 "${TEST_BOOT_SECTOR}" 129 | RESULT=$(${SCRIPT_HOME}/eddosboot.sh DEBUG SHOW SECTOR_COUNT "${TEST_BOOT_SECTOR}") 130 | verify_test "Test 4.b" "5" "${RESULT}" 131 | 132 | ${SCRIPT_HOME}/eddosboot.sh DEBUG CHANGE SECTOR_COUNT 2880 "${TEST_BOOT_SECTOR}" 133 | RESULT=$(${SCRIPT_HOME}/eddosboot.sh DEBUG SHOW SECTOR_COUNT "${TEST_BOOT_SECTOR}") 134 | verify_test "Test 4.c" "2880" "${RESULT}" 135 | 136 | # test copying boot sector 137 | cp "${SOURCE_BOOT_DISK}" "${TEST_BOOT_DISK}" 138 | 139 | SOURCE_FILE_SIZE=$(stat -f%z "${SOURCE_BOOT_DISK}") 140 | TARGET_FILE_SIZE=$(stat -f%z "${TEST_BOOT_DISK}") 141 | if [ ! "${SOURCE_FILE_SIZE}" = "${TARGET_FILE_SIZE}" ]; then 142 | echo "Test 5.a failure: copied file is not correct size after boot sector copy, should be: ${SOURCE_FILE_SIZE}, but is: ${TARGET_FILE_SIZE}" 143 | exit 1 144 | fi 145 | echo "Test 5.a passed: copied file is correct size." 146 | 147 | ${SCRIPT_HOME}/eddosboot.sh DEBUG COPY_BOOT_SECTOR "${TEST_BOOT_SECTOR}" "${TEST_BOOT_DISK}" 148 | RESULT=$(${SCRIPT_HOME}/eddosboot.sh DEBUG SHOW SECTOR_SIZE "${TEST_BOOT_DISK}") 149 | verify_test "Test 5.b" "19" "${RESULT}" 150 | RESULT=$(${SCRIPT_HOME}/eddosboot.sh DEBUG SHOW SECTOR_COUNT "${TEST_BOOT_DISK}") 151 | verify_test "Test 5.c" "2880" "${RESULT}" 152 | TARGET_FILE_SIZE=$(stat -f%z "${TEST_BOOT_DISK}") 153 | if [ ! "${SOURCE_FILE_SIZE}" = "${TARGET_FILE_SIZE}" ]; then 154 | echo "Test 5.d failure: copied file is not correct size after boot sector copy, should be: ${SOURCE_FILE_SIZE}, but is: ${TARGET_FILE_SIZE}" 155 | exit 1 156 | fi 157 | echo "Test 5.d passed: copied file is correct size after boot sector copy" 158 | 159 | ${SCRIPT_HOME}/eddosboot.sh DEBUG COPY_BOOT_SECTOR "${SOURCE_BOOT_DISK}" "${TEST_BOOT_DISK}" 160 | RESULT=$(${SCRIPT_HOME}/eddosboot.sh DEBUG SHOW SECTOR_SIZE "${TEST_BOOT_DISK}") 161 | verify_test "Test 6.a" "512" "${RESULT}" 162 | RESULT=$(${SCRIPT_HOME}/eddosboot.sh DEBUG SHOW SECTOR_COUNT "${TEST_BOOT_DISK}") 163 | verify_test "Test 6.b" "1440" "${RESULT}" 164 | TARGET_FILE_SIZE=$(stat -f%z "${TEST_BOOT_DISK}") 165 | if [ ! "${SOURCE_FILE_SIZE}" = "${TARGET_FILE_SIZE}" ]; then 166 | echo "Test 6.c failure: copied file is not correct size after boot sector copy, should be: ${SOURCE_FILE_SIZE}, but is: ${TARGET_FILE_SIZE}" 167 | exit 1 168 | fi 169 | echo "Test 5.a passed: copied file is correct size after boot sector copy" 170 | 171 | # arg 1: test number 172 | # arg 2: expected sector size 173 | # arg 3: expected sector count 174 | # arg 4: expected file size 175 | check_boot_sector() { 176 | TEST_NUMBER="${1}" 177 | EXPECTED_SECTOR_SIZE="${2}" 178 | EXPECTED_SECTOR_COUNT="${3}" 179 | EXPECTED_DISK_SIZE="${4}" 180 | TARGET_FILE_SIZE=$(stat -f%z "${TEST_BOOT_DISK}") 181 | if [ ! "${EXPECTED_DISK_SIZE}" = "${TARGET_FILE_SIZE}" ]; then 182 | echo "Test ${TEST_NUMBER}.a failure: created file is not correct size after creation, should be: ${EXPECTED_DISK_SIZE}, but is: ${TARGET_FILE_SIZE}" 183 | exit 1 184 | fi 185 | echo "Test ${TEST_NUMBER}.a passed, disk is expected size: ${EXPECTED_DISK_SIZE}" 186 | RESULT=$(${SCRIPT_HOME}/eddosboot.sh DEBUG SHOW SECTOR_SIZE "${TEST_BOOT_DISK}") 187 | verify_test "Test ${TEST_NUMBER}.b" "${EXPECTED_SECTOR_SIZE}" "${RESULT}" 188 | RESULT=$(${SCRIPT_HOME}/eddosboot.sh DEBUG SHOW SECTOR_COUNT "${TEST_BOOT_DISK}") 189 | verify_test "Test ${TEST_NUMBER}.c" "${EXPECTED_SECTOR_COUNT}" "${RESULT}" 190 | } 191 | 192 | # arg 1: test number 193 | # arg 2: expected sector size 194 | # arg 3: expected sector count 195 | check_boot_disk() { 196 | check_boot_sector "${1}" "${2}" "${3}" "$(($2 * $3))" 197 | } 198 | 199 | # test boot disk creation 200 | 201 | rm "${TEST_BOOT_DISK}" 202 | ${SCRIPT_HOME}/eddosboot.sh DEBUG CREATE BOOT_DISK FREEDOS "${TEST_BOOT_DISK}" 203 | check_boot_disk 7 512 2880 204 | 205 | rm "${TEST_BOOT_DISK}" 206 | ${SCRIPT_HOME}/eddosboot.sh DEBUG CREATE BOOT_DISK FREEDOS "1.4MB" "${TEST_BOOT_DISK}" 207 | check_boot_disk 8 512 2880 208 | 209 | rm "${TEST_BOOT_DISK}" 210 | ${SCRIPT_HOME}/eddosboot.sh DEBUG CREATE BOOT_DISK FREEDOS "1200K" "${TEST_BOOT_DISK}" 211 | check_boot_disk 10 512 $((1200 * 2)) 212 | 213 | rm "${TEST_BOOT_DISK}" 214 | ${SCRIPT_HOME}/eddosboot.sh DEBUG CREATE BOOT_DISK FREEDOS "720K" "${TEST_BOOT_DISK}" 215 | check_boot_disk 11 512 1440 216 | 217 | rm "${TEST_BOOT_DISK}" 218 | ${SCRIPT_HOME}/eddosboot.sh DEBUG CREATE BOOT_DISK FREEDOS "640K" "${TEST_BOOT_DISK}" 219 | check_boot_disk 12 512 $((640 * 2)) 220 | 221 | rm "${TEST_BOOT_DISK}" 222 | ${SCRIPT_HOME}/eddosboot.sh DEBUG CREATE BOOT_DISK FREEDOS "360K" "${TEST_BOOT_DISK}" 223 | check_boot_disk 13 512 $((360 * 2)) 224 | 225 | rm "${TEST_BOOT_DISK}" 226 | ${SCRIPT_HOME}/eddosboot.sh DEBUG CREATE BOOT_DISK FREEDOS "320K" "${TEST_BOOT_DISK}" 227 | check_boot_disk 14 512 640 228 | 229 | rm "${TEST_BOOT_DISK}" 230 | ${SCRIPT_HOME}/eddosboot.sh DEBUG CREATE BOOT_DISK FREEDOS "180K" "${TEST_BOOT_DISK}" 231 | check_boot_disk 15 512 $((180 * 2)) 232 | 233 | rm "${TEST_BOOT_DISK}" 234 | ${SCRIPT_HOME}/eddosboot.sh DEBUG CREATE BOOT_DISK FREEDOS "160K" "${TEST_BOOT_DISK}" 235 | check_boot_disk 16 512 320 236 | 237 | # test boot sector creation 238 | 239 | rm "${TEST_BOOT_DISK}" 240 | ${SCRIPT_HOME}/eddosboot.sh DEBUG CREATE BOOT_SECTOR "${TEST_BOOT_DISK}" 241 | check_boot_sector 17 512 2880 512 242 | 243 | rm "${TEST_BOOT_DISK}" 244 | ${SCRIPT_HOME}/eddosboot.sh DEBUG CREATE BOOT_SECTOR "1.4MB" "${TEST_BOOT_DISK}" 245 | check_boot_sector 18 512 2880 512 246 | 247 | rm "${TEST_BOOT_DISK}" 248 | ${SCRIPT_HOME}/eddosboot.sh DEBUG CREATE BOOT_SECTOR "1200K" "${TEST_BOOT_DISK}" 249 | check_boot_sector 20 512 $((1200 * 2)) 512 250 | 251 | rm "${TEST_BOOT_DISK}" 252 | ${SCRIPT_HOME}/eddosboot.sh DEBUG CREATE BOOT_SECTOR "720K" "${TEST_BOOT_DISK}" 253 | check_boot_sector 21 512 1440 512 254 | 255 | rm "${TEST_BOOT_DISK}" 256 | ${SCRIPT_HOME}/eddosboot.sh DEBUG CREATE BOOT_SECTOR "640K" "${TEST_BOOT_DISK}" 257 | check_boot_sector 22 512 $((640 * 2)) 512 258 | 259 | rm "${TEST_BOOT_DISK}" 260 | ${SCRIPT_HOME}/eddosboot.sh DEBUG CREATE BOOT_SECTOR "360K" "${TEST_BOOT_DISK}" 261 | check_boot_sector 23 512 $((360 * 2)) 512 262 | 263 | rm "${TEST_BOOT_DISK}" 264 | ${SCRIPT_HOME}/eddosboot.sh DEBUG CREATE BOOT_SECTOR "320K" "${TEST_BOOT_DISK}" 265 | check_boot_sector 24 512 640 512 266 | 267 | rm "${TEST_BOOT_DISK}" 268 | ${SCRIPT_HOME}/eddosboot.sh DEBUG CREATE BOOT_SECTOR "180K" "${TEST_BOOT_DISK}" 269 | check_boot_sector 25 512 $((180 * 2)) 512 270 | 271 | rm "${TEST_BOOT_DISK}" 272 | ${SCRIPT_HOME}/eddosboot.sh DEBUG CREATE BOOT_SECTOR "160K" "${TEST_BOOT_DISK}" 273 | check_boot_sector 26 512 320 512 274 | 275 | rm "${TEST_BOOT_SECTOR}" 276 | rm "${TEST_BOOT_DISK}" 277 | 278 | echo "" 279 | echo "All Tests Passed!" 280 | 281 | exit 0 -------------------------------------------------------------------------------- /scripts/testhexlib.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ################################################################################# 4 | # 5 | # testhexlib.sh - Test suite for hexlib.sh 6 | # 7 | # written by Jason Baker (jason@onejasonforsale.com) 8 | # project's github: https://github.com/codercowboy/freedosbootdisks 9 | # more info: http://www.codercowboy.com 10 | # 11 | ################################################################################# 12 | # 13 | # UPDATES: 14 | # 15 | # 2018/10/15 16 | # - Initial version 17 | # 18 | ################################################################################# 19 | # 20 | # Copyright (c) 2018, Coder Cowboy, LLC. All rights reserved. 21 | # 22 | # Redistribution and use in source and binary forms, with or without 23 | # modification, are permitted provided that the following conditions are met: 24 | # 25 | # 1. Redistributions of source code must retain the above copyright notice, this 26 | # list of conditions and the following disclaimer. 27 | # 28 | # 2. Redistributions in binary form must reproduce the above copyright notice, 29 | # this list of conditions and the following disclaimer in the documentation 30 | # and/or other materials provided with the distribution. 31 | # 32 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 33 | # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 34 | # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 35 | # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 36 | # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 37 | # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 38 | # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 39 | # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 40 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 41 | # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 42 | # 43 | # The views and conclusions contained in the software and documentation are those 44 | # of the authors and should not be interpreted as representing official policies, 45 | # either expressed or implied. 46 | # 47 | ################################################################################# 48 | 49 | DEBUG_HEXLIB="true" 50 | 51 | SCRIPT_HOME="`dirname ${BASH_SOURCE[0]}`" 52 | 53 | source "${SCRIPT_HOME}/hexlib.sh" 54 | 55 | TEST_FILE="${SCRIPT_HOME}/test.tmp" 56 | debug_log "TEST_FILE: ${TEST_FILE}" 57 | if [ -f "${TEST_FILE}" ]; then 58 | rm "${TEST_FILE}" 59 | fi 60 | echo -n "ABCD" > "${TEST_FILE}" 61 | 62 | RESULT=$(extract_string_from_file 0 4 "${TEST_FILE}") 63 | verify_test "Test 1.a" "ABCD" "${RESULT}" 64 | 65 | RESULT=$(extract_string_from_file 1 2 "${TEST_FILE}") 66 | verify_test "Test 1.b" "BC" "${RESULT}" 67 | 68 | RESULT=$(extract_string_from_file 3 1 "${TEST_FILE}") 69 | verify_test "Test 1.c" "D" "${RESULT}" 70 | 71 | RESULT=$(extract_string_from_file 32 40 "${TEST_FILE}") 72 | verify_test "Test 1.d" "" "${RESULT}" 73 | 74 | RESULT=$(reverse_hex_order "0x00ABCD03") 75 | verify_test "Test 2.a" "0x03CDAB00" "${RESULT}" 76 | 77 | RESULT=$(reverse_hex_order "0x00AB") 78 | verify_test "Test 2.b" "0xAB00" "${RESULT}" 79 | 80 | RESULT=$(reverse_hex_order "0xAB") 81 | verify_test "Test 2.c" "0xAB" "${RESULT}" 82 | 83 | RESULT=$(convert_hex_to_number "0x00") 84 | verify_test "Test 3.a" "0" "${RESULT}" 85 | 86 | RESULT=$(convert_hex_to_number "0x01") 87 | verify_test "Test 3.b" "1" "${RESULT}" 88 | 89 | RESULT=$(convert_hex_to_number "0x13") 90 | verify_test "Test 3.c" "19" "${RESULT}" 91 | 92 | RESULT=$(convert_hex_to_number "0x0F") 93 | verify_test "Test 3.d" "15" "${RESULT}" 94 | 95 | RESULT=$(convert_hex_to_number "0x0A") 96 | verify_test "Test 3.e" "10" "${RESULT}" 97 | 98 | RESULT=$(convert_hex_to_number "0x0001") 99 | verify_test "Test 3.f" "1" "${RESULT}" 100 | 101 | RESULT=$(convert_hex_to_number "0xFF00FF") 102 | verify_test "Test 3.g" "16711935" "${RESULT}" 103 | 104 | RESULT=$(convert_hex_to_ascii_string "0x4A61736F6E") 105 | verify_test "Test 4.a" "Jason" "${RESULT}" 106 | 107 | RESULT=$(convert_number_to_hex 0) 108 | verify_test "Test 5.a" "0x00" "${RESULT}" 109 | 110 | RESULT=$(convert_number_to_hex 1) 111 | verify_test "Test 5.b" "0x01" "${RESULT}" 112 | 113 | RESULT=$(convert_number_to_hex 15) 114 | verify_test "Test 5.c" "0x0F" "${RESULT}" 115 | 116 | RESULT=$(convert_number_to_hex 255) 117 | verify_test "Test 5.d" "0xFF" "${RESULT}" 118 | 119 | RESULT=$(convert_number_to_hex 123456789) 120 | verify_test "Test 5.e" "0x075BCD15" "${RESULT}" 121 | 122 | RESULT=$(convert_ascii_string_to_hex "Jason") 123 | verify_test "Test 6.a" "0x4A61736F6E" "${RESULT}" 124 | 125 | # test file before here was "ABCD" 126 | 127 | # lowercase to "abcd" 128 | replace_bytes 0 "0x61626364" "${TEST_FILE}" 129 | RESULT=`cat ${TEST_FILE}` 130 | verify_test "Test 7.a" "abcd" "${RESULT}" 131 | 132 | # write "A" in first byte 133 | replace_bytes 0 "0x41" "${TEST_FILE}" 134 | RESULT=`cat ${TEST_FILE}` 135 | verify_test "Test 7.b" "Abcd" "${RESULT}" 136 | 137 | # write "D" in fourth byte 138 | replace_bytes 3 "0x44" "${TEST_FILE}" 139 | RESULT=`cat ${TEST_FILE}` 140 | verify_test "Test 7.c" "AbcD" "${RESULT}" 141 | 142 | # write "EFG" at end 143 | replace_bytes 4 "0x454647" "${TEST_FILE}" 144 | RESULT=`cat ${TEST_FILE}` 145 | verify_test "Test 7.d" "AbcDEFG" "${RESULT}" 146 | 147 | echo -n "ABCD" > "${TEST_FILE}" 148 | 149 | # write "a" in first byte 150 | replace_string_in_file 0 "a" "${TEST_FILE}" 151 | RESULT=`cat ${TEST_FILE}` 152 | verify_test "Test 8.a" "aBCD" "${RESULT}" 153 | 154 | # write "d" in fourth byte 155 | replace_string_in_file 3 "d" "${TEST_FILE}" 156 | RESULT=`cat ${TEST_FILE}` 157 | verify_test "Test 8.b" "aBCd" "${RESULT}" 158 | 159 | # write "XY" in second/third byte 160 | replace_string_in_file 1 "XY" "${TEST_FILE}" 161 | RESULT=`cat ${TEST_FILE}` 162 | verify_test "Test 8.c" "aXYd" "${RESULT}" 163 | 164 | # write "ABCDEFGHIJK" over file 165 | replace_string_in_file 0 "ABCDEFGHIJK" "${TEST_FILE}" 166 | RESULT=`cat ${TEST_FILE}` 167 | verify_test "Test 8.d" "ABCDEFGHIJK" "${RESULT}" 168 | 169 | # write 15 to file 170 | rm "${TEST_FILE}" 171 | HEX_NUMBER=$(convert_number_to_hex 15) 172 | replace_bytes 0 "${HEX_NUMBER}" "${TEST_FILE}" 173 | RESULT=$(extract_number_from_file 0 1 "${TEST_FILE}") 174 | verify_test "Test 9.a" "15" "${RESULT}" 175 | 176 | #write 1 to file 177 | rm "${TEST_FILE}" 178 | HEX_NUMBER=$(convert_number_to_hex 1) 179 | replace_bytes 0 "${HEX_NUMBER}" "${TEST_FILE}" 180 | RESULT=$(extract_number_from_file 0 1 "${TEST_FILE}") 181 | verify_test "Test 9.b" "1" "${RESULT}" 182 | 183 | #write 0 to file 184 | rm "${TEST_FILE}" 185 | HEX_NUMBER=$(convert_number_to_hex 0) 186 | replace_bytes 0 "${HEX_NUMBER}" "${TEST_FILE}" 187 | RESULT=$(extract_number_from_file 0 1 "${TEST_FILE}") 188 | verify_test "Test 9.c" "0" "${RESULT}" 189 | 190 | # write 255 to file twice (which will read out as 65535) 191 | rm "${TEST_FILE}" 192 | HEX_NUMBER=$(convert_number_to_hex 255) 193 | replace_bytes 0 "${HEX_NUMBER}" "${TEST_FILE}" 194 | replace_bytes 1 "${HEX_NUMBER}" "${TEST_FILE}" 195 | RESULT=$(extract_number_from_file 0 2 "${TEST_FILE}") 196 | verify_test "Test 9.d" "65535" "${RESULT}" 197 | RESULT=$(extract_number_from_file 0 1 "${TEST_FILE}") 198 | verify_test "Test 9.e" "255" "${RESULT}" 199 | RESULT=$(extract_number_from_file 1 1 "${TEST_FILE}") 200 | verify_test "Test 9.f" "255" "${RESULT}" 201 | 202 | rm "${TEST_FILE}" 203 | replace_bytes 0 "0x00000000" "${TEST_FILE}" 204 | RESULT=$(extract_number_from_file 1 4 "${TEST_FILE}") 205 | verify_test "Test 9.g" "0" "${RESULT}" 206 | 207 | replace_number_in_file 1 255 "${TEST_FILE}" 208 | echo "Current file contents: `extract_bytes 0 4 "${TEST_FILE}"`" 209 | RESULT=$(extract_number_from_file 1 1 "${TEST_FILE}") 210 | verify_test "Test 10.a" "255" "${RESULT}" 211 | RESULT=$(extract_number_from_file 0 1 "${TEST_FILE}") 212 | verify_test "Test 10.b" "0" "${RESULT}" 213 | RESULT=$(extract_number_from_file 2 1 "${TEST_FILE}") 214 | verify_test "Test 10.c" "0" "${RESULT}" 215 | RESULT=$(extract_number_from_file 3 1 "${TEST_FILE}") 216 | verify_test "Test 10.d" "0" "${RESULT}" 217 | RESULT=$(extract_number_from_file 1 3 "${TEST_FILE}") 218 | verify_test "Test 10.e" "255" "${RESULT}" 219 | 220 | rm "${TEST_FILE}" 221 | replace_bytes 0 "0x00000000" "${TEST_FILE}" 222 | RESULT=$(extract_number_from_file 1 4 "${TEST_FILE}") 223 | verify_test "Test 10.f" "0" "${RESULT}" 224 | 225 | replace_number_in_file 1 65535 "${TEST_FILE}" 226 | echo "Current file contents: `extract_bytes 0 4 "${TEST_FILE}"`" 227 | RESULT=$(extract_number_from_file 0 1 "${TEST_FILE}") 228 | verify_test "Test 10.g" "0" "${RESULT}" 229 | RESULT=$(extract_number_from_file 1 1 "${TEST_FILE}") 230 | verify_test "Test 10.h" "255" "${RESULT}" 231 | RESULT=$(extract_number_from_file 2 1 "${TEST_FILE}") 232 | verify_test "Test 10.i" "255" "${RESULT}" 233 | RESULT=$(extract_number_from_file 3 1 "${TEST_FILE}") 234 | verify_test "Test 10.j" "0" "${RESULT}" 235 | RESULT=$(extract_number_from_file 1 2 "${TEST_FILE}") 236 | verify_test "Test 10.k" "65535" "${RESULT}" 237 | RESULT=$(extract_number_from_file 100 20 "${TEST_FILE}") 238 | verify_test "Test 10.l" "0" "${RESULT}" 239 | 240 | #decimal 312 is hex 0x0138 241 | rm "${TEST_FILE}" 242 | replace_bytes 0 "0x00000000" "${TEST_FILE}" 243 | RESULT=$(extract_number_from_file 1 4 "${TEST_FILE}") 244 | verify_test "Test 10.m" "0" "${RESULT}" 245 | replace_number_in_file 1 312 "${TEST_FILE}" 246 | echo "Current file contents: `extract_bytes 0 4 "${TEST_FILE}"`" 247 | RESULT=$(extract_number_from_file 1 2 "${TEST_FILE}") 248 | verify_test "Test 10.n" "312" "${RESULT}" 249 | 250 | rm "${TEST_FILE}" 251 | 252 | echo "" 253 | echo "All Tests Passed!" 254 | 255 | exit 0 --------------------------------------------------------------------------------