├── 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 |
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 |
44 |
45 |
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
--------------------------------------------------------------------------------