2

I have a DOS based HDD utility called spinrite. I want to create a bootable flash drive with the freedos OS and once created copy into the drive the executable utility.

I tried using gparted to partition the drive, formated it as Fat32 and set the Boot flag. once done I cannot see how to install the OS and add the executable. I have an image file of Freedos, if I try making the flash drive with it then it's not bootable. Any help is greatly appreciated.

Guy D'Amico
  • 31
  • 1
  • 4
  • 1
    do you actually need to have a bootable freedos on a USB flash drive or do you just need the ability to occasionally boot freedos images (e.g. from the grub menu)? – cas Jan 07 '18 at 02:00
  • Yes, I need a bootable Flash Drive with a copy of Freedos on it. Ideally the Flash Drive once created would allow more software utilities to be added to it. – Guy D'Amico Jan 08 '18 at 13:58
  • Is there any reason the downloadable freedos 1.2 images don't work for you? normally you just write them out to USB flash with `dd` or `cat`. BTW, the reason I asked whether you actually need a USB stick is that it's actually pretty easy to boot a freedos image from the grub menu using `memdisk` from `syslinux`. It's almost as easy to boot freedos & other images over the network (but requires a fair bit of once-off setup). If you don't need to boot it on multiple machines that aren't on the same LAN, it's a lot more convenient to not have to mess around with USB sticks. – cas Jan 08 '18 at 23:10
  • So the Freedos image works but I haven't found how to add additional software utilities to the flash drive afterwards. So I was using two thumb drives, one with the bootable Freedos and the other with the utilities. In my case I am retired, learning Linux along the way. I have enough knowledge to help my retired neighbors with problems on their WINDOWS boxes and move some of the more adventurous over to Linux Mint. So going to their homes to help works using flash drives. – Guy D'Amico Jan 10 '18 at 00:15
  • you should just be able to copy files from one mounted USB stick to the other. But, as noted in my answer, the standard freedos boot image doesn't have much free space - which is why i deleted everything but the bare minimum needed to boot. – cas Jan 10 '18 at 00:22
  • That does not work for me, when I burn the image I can no longer add anything to the flash drive. Even if I open the Flash Drive as Root, I cannot add to it. Burning the image eliminates any free space. df command shows zero available space/ – Guy D'Amico Jan 10 '18 at 01:25
  • how are you "burning" the flash drive? which image are you using? if you're copying an ISO CD-ROM image then that will explain why you can't write - ISO images are read-only. You can create them with whatever you want on them, but you can't modify them once created. – cas Jan 10 '18 at 01:46
  • That then is the problem, I am using ISO. I have not spent any time to learn how to create an ISO, looks like it's time ;-) – Guy D'Amico Jan 10 '18 at 15:43
  • or you could just use a floppy or USB image with a read-write vfat filesystem on it rather than a read-only iso9660 filesystem. – cas Jan 11 '18 at 05:02
  • How does one to this? I haven't seen where I have any options when burning an ISO. Is it done somehow using DD? – Guy D'Amico Jan 12 '18 at 00:52
  • No, you just don't use an ISO9660 image. You download and use one of the floppy or USB images that are formatted with a FAT filesystem. iso9660 is not a "normal" (i.e. read-write) filesystem, it's a read-only image format for CD and DVD ROMs. You might be able to use one of the large "freedos 1.2 installer" images by booting it and then following the menu options to create a bootable freedos floppy or USB stick (i've never used them, so i don't know if they can install to imagefile/floppy/usb or only to a hard disk partition). – cas Jan 12 '18 at 01:06

2 Answers2

3

It seems that the official FreeDOS images (as of this writing) were not meant to be used as "live CDs" but rather as installation media. So to make a bootable media for your purposes you could modify one of the official FreeDOS installer images. However, you maybe restricted by the size of the media you choose especially when using floppy images.

In this answer I will focus on creating, in Linux, just a minimal FreeDOS boot disk image (any size you need) from scratch and then writing the MBR, VBR, a minimal set of FreeDOS files required for boot plus your single program (spinrite) or any DOS utility like BIOS update tools, etc.

You can then boot of this FreeDOS image using PXE boot or write it to a USB drive with dd to create a FreeDOS boot drive. Ofcourse you can extend the steps used here to create any FreeDOS media you'd like including adding the full suite of software that comes with the FreeDOS Full edition.

On a Windows machine you could use a tool like Rufus to do do this. But on Linux you can use ms-sys (the source code of which Rufus uses internally).

Below are the steps for creating a bootable FreeDOS image:


WARNING / DISCLAIMER!!! Some commands used below have the potential to wipe data from your disk drives if used incorrectly. Read the man page for each program to understand the command usage before proceeding. You might want to try these commands on a secondary/virtual machine that doesn't have your valuable data on it.


Step 1: Install Prerequites (ms-sys):

  • Install ms-sys from source if its not available with your package manager:

    $ wget https://sourceforge.net/projects/ms-sys/files/ms-sys%20stable/2.6.0/ms-sys-2.6.0.tar.gz
    $ tar -xzvf ms-sys-2.6.0.tar.gz
    $ cd ms-sys-2.6.0
    
  • Compiling ms-sys requires msgfmt from the gettext package which can be installed on Debian/Ubuntu using:

    $ sudo apt install gettext
    
  • Compile and Install:

    $ make
    $ sudo make install
    

Step 2: Create a blank disk image and create a msdos partition:

  • Create an empty file for the disk image:

    $ truncate -s 50M disk.img
    

    Note: Here a 50 MiB size disk image is created but you can make this any size you need

  • Partition the disk image:

    $ fdisk disk.img
    Command (m for help): o
        Created a new DOS disklabel with disk identifier 0x1234abcd.
    
    Command (m for help): n
        Partition type
           p   primary (0 primary, 0 extended, 4 free)
           e   extended (container for logical partitions)
        Select (default p): p
        Partition number (1-4, default 1): <ENTER>
        First sector (2048-102399, default 2048): 2048
        Last sector, +sectors or +size{K,M,G,T,P} (2048-102399, default 102399): <ENTER>
    
    Command (m for help): t
        Selected partition 1
        Partition type (type L to list all types): c
    
    Command (m for help): a
        Selected partition 1
        The bootable flag on partition 1 is enabled now.
    
    Command (m for help): w
    

    Note: The fdisk commands above assume you want a FAT32 file-system. If you want to use a FAT16 file-system then for the question above Partition type (type L to list all types): enter e instead of c

Step 3: Confirm location of the starting sector of the first partition:

  • Use fdisk to determine the starting sector:

    $ fdisk -l disk.img
    Disk disk.img: 50 MiB, 52428800 bytes, 102400 sectors
    Units: sectors of 1 * 512 = 512 bytes
    Sector size (logical/physical): 512 bytes / 512 bytes
    I/O size (minimum/optimal): 512 bytes / 512 bytes
    Disklabel type: dos
    Disk identifier: 0x1234abcd
    
    Device     Boot Start    End Sectors Size Id Type
    disk.img1  *     2048 102399  100352  49M  c W95 FAT32 (LBA)
    

    Note: From the above fdisk output we can see that the starting sector offset is 2048 sectors or 2048 x sector_size bytes = 2048 x 512 bytes = 1048576 bytes. Actually we explicitly specified the starting sector in Step 2 but I included this step as it might be useful when the partition was already created. These numbers: 2048 and 1048576 are used in the commands that follow.

Step 4: Format the partition with a FAT file-system

  • Search for a free loop device:

    $ losetup -f
    /dev/loop0
    
  • Create a loop device of the partition (which is at offset=1048576 of the disk image):

    $ sudo losetup -o1048576 /dev/loop0 disk.img
    
  • Create FAT File System:

    • To create a FAT16 file system:

      $ sudo mkfs.vfat -F16 -R8 -h2048 /dev/loop0
      
    • To create a FAT32 file system:

      $ sudo mkfs.vfat -F32 -h2048 /dev/loop0
      

      Note: In the mkfs.vfat parameter -h2048 is required. mkfs.vfat doesn't write the hidden sectors before the partition to the boot record unless you specify this parameter and it is required for booting the image). Again here 2048 is the partition 1 offset in sectors as determined in Step 3. The parameter -R8 is optional but recommended.

Step 5: Use ms-sys to write to the Master Boot Record (MBR) and Volume Boot Record (VBR):

  • First write the VBR while the partition is still loaded as a loop device:

    • To create a FAT16 file system:

      $ sudo ms-sys --fat16free /dev/loop0
      
    • To create a FAT32 file system:

      $ sudo ms-sys --fat32free /dev/loop0
      

      Notes:

      • Don't use this command: ms-sys --partition /dev/loop0 even thought it is discussed in some of the ms-sys documentation as being required in some cases. It will overwrite the hidden sectors field already correctly written by mkfs.vfat
      • ms-sys only writes to the first boot record. ms-sys unlike Rufus does not write to FAT32's backup boot record but this shouldn't prevent the image from being bootable.
  • Next unload/detach the disk image file from the loop device:

    $ sudo losetup -d /dev/loop0
    
  • And finally write a Windows 7 MBR to the disk image:

    $ ms-sys --mbr7 --force disk.img
    

    Note: ms-sys requires the --force argument when writing to regular (non-device) files.

Step 6: Write Basic FreeDos files and any other programs you need to the partition on the disk image:

  • Mount partition:

    $ mkdir mnt
    $ sudo mount -o loop,offset=1048576 disk.img mnt/
    
  • Download and extract required FreeDOS files:

    $ wget https://github.com/pbatard/rufus/archive/v3.6.tar.gz
    $ tar -xvf v3.6.tar.gz rufus-3.6/res/freedos/
    

    Note: These files are downloaded from the Rufus github repository but are extracted from the official FreeDOS website. See the readme.txt on https://github.com/pbatard/rufus/tree/master/res/freedos/ for detail on were Rufus gets the binaries from the official FreeDOS sources.

  • Copy files to partition:

    $ sudo mkdir mnt/LOCALE
    $ sudo cp rufus-3.6/res/freedos/!(COMMAND.COM|KERNEL.SYS) mnt/LOCALE/
    $ sudo cp rufus-3.6/res/freedos/{COMMAND.COM,KERNEL.SYS} mnt/
    $ printf '@echo off\r\nset PATH=.;\\;\\LOCALE\r\necho Using US-English keyboard with US-English codepage [437]\r\n' | sudo tee mnt/AUTOEXEC.BAT
    $ sudo fatattr +h +s mnt/COMMAND.COM
    $ sudo fatattr +h +s mnt/KERNEL.SYS
    

    Notes:

    • The only files that are really required to make the disk image bootable are COMMAND.COM and KERNEL.SYS. The rest of the files are optional
    • You can now also copy any other files you have to the disk image as well before unmounting it (eg: spinrite.exe).
    • The fatattr commands are optional but add hidden and system attributes to the files COMMAND.COM and KERNEL.SYS as is customary. On a Debian/Ubuntu system you can install the fatattr program using sudo apt-get install fatattr

Step 7: You are Done!

  • Unmount the disk image:

    $ sudo umount mnt/
    
moo
  • 183
  • 1
  • 7
1

Here's what I do to customise FreeDOS images:

  1. start with a bootable floppy image that I downloaded from the Freedos site. Unfortunately it's full of stuff I don't need just to run some once-off utility like a BIOS updater.

  2. mount a copy of it with:

    mkdir -p ./floppy
    cp -a ./freedos-1440kb.img freedos-empty.img
    mount -o loop,rw freedos-empty.img ./floppy
    
  3. cd ./floppy and delete everything that isn't needed. This should end up with about 1.2 or 1.3MB free on the 1.44MB image.

  4. cd .. ; umount ./floppy

  5. That gives me an almost empty bootable image which I can use to make as many custom images as I want. I then make a copy of that and then copy whatever I need on to it. e.g.

    cp -a ./freedos-empty.img ./freedos-spinrite.img
    mount -o loop,rw freedos-spinrite.img ./floppy
    cp spinrite.exe ./floppy
    umount ./floppy
    

This image can then be copied to a floppy drive, flash drive, etc. e.g. cat freedos-spinrite.img > /dev/sdX (where sdX is the device node for your USB stick). I almost never bother doing this because I can never find an empty, usable flash drive when I need one....it's also more work and takes longer than using grub or tftp menus. And it's slower to boot a USB stick than a disk image stored on the local hard disk or on my tftp server.

In my case, I copy it to my /boot/images/ directory and run update-grub...and then use scp to copy it to other machines where it might be needed and run update-grub on them too via ssh.

I also copy it to my /var/lib/tfptboot/freedos/ and run a script I wrote to generate menu entries for all *.img files in that directory.

This lets me boot the freedos image from the grub menu at boot up, AND over the network via ipxe and tftp on any machine that has a "boot from network card" option at boot time (i.e. almost all machines these days. All if you include the fact that ipxe can be booted from grub too).

I've used this to build bootable images for updating BIOSes on motherboards, reflash LSI SAS cards into IT mode, and apply firmware updates to, e.g., some Seagate hard disks.

BTW, this is why I like to make "over-sized" /boot partitions (1 or 2GB or more) - so I can boot any image of any "reasonable" size. Also so that I don't run out of space in /boot and have to clear out my old kernel images all the time. It's also useful for, e.g., booting gparted or clonezilla images.


Extra stuff: setting up grub

Setting up tftp for this is a fair bit of work initially so I won't go into that here (I'm pretty sure I've described the process in another answer on this site, and my tftp scripts are on my github account - but I haven't uploaded the memdisk/freedos scripts), but there's very little that needs to be done for grub:

  1. install syslinux (or at least, get a copy of the memdisk binary from it).
  2. cp memdisk /boot
  3. mkdir -p /boot/images
  4. copy your bootable *.img, *.iso image file(s) into /boot/images.
  5. copy the script 42_memdisk (see below) into /etc/grub.d/ and make it executable with chmod +x /etc/grub.d/42_memdisk
  6. run update-grub as root

Note: the above works for Debian and most related/derivative distributions like Ubuntu and Mint. Other distros have slightly different setups for grub, so you'd have to adjust the procedure accordingly.

memdisk can boot any disk image that's bootable - from floppy images to CD-ROM/DVD images, to hard disk images.

42_memdisk (this is the script that does the work of generating menu entries for grub):

#!/bin/sh
set -e

IMAGES=/boot/images
. /usr/lib/grub/grub-mkconfig_lib
if test -e /boot/memdisk ; then
  echo "Found memdisk: $MEMDISKPATH" >&2
  MEMDISKPATH="$( make_system_path_relative_to_its_root "/boot/memdisk" )"

  find "$IMAGES" -name '*.img' -o -name '*.iso' | sort | 
  while read image ; do
      IMAGEPATH="$( make_system_path_relative_to_its_root "$image" )"
      echo "Found image: $IMAGEPATH" >&2
      cat << EOF
menuentry "Bootable image: $(basename $IMAGEPATH | sed -E -e 's/\.(img|iso)$//i')" {
EOF
      prepare_grub_to_access_device ${GRUB_DEVICE_BOOT} | sed -e 's/^/\t/'
      cat << EOF
        linux16 $MEMDISKPATH bigraw
        initrd16 $IMAGEPATH
}
EOF
  done
fi

IIRC, this is modified from a script I found somewhere years ago while googling how to do stuff like this (I can't remember where).

Example output:

# update-grub
Generating grub configuration file ...
Found linux image: /boot/vmlinuz-4.14.0-2-amd64
Found initrd image: /boot/initrd.img-4.14.0-2-amd64
Found linux image: /boot/vmlinuz-4.14.0-1-amd64
Found initrd image: /boot/initrd.img-4.14.0-1-amd64
Found linux image: /boot/vmlinuz-4.12.0-2-amd64
Found initrd image: /boot/initrd.img-4.12.0-2-amd64
Found iPXE image: /boot/ipxe.lkrn
Found memtest86 image: /memtest86.bin
Found memtest86+ image: /memtest86+.bin
Found memdisk:
Found image: /images/LSI.img
Found image: /images/Seagate-PH-CC49.img
Found image: /images/fd-asus-m5a97.img
Found image: /images/freedos-empty.img
done
cas
  • 1
  • 7
  • 119
  • 185
  • Wow, this is way more than I was hoping for. This is a keeper! – Guy D'Amico Jan 10 '18 at 00:06
  • I'm glad it's of use. BTW, if you are running KVM or VirtualBox or similar, you can make a minimal Linux VM and use that to test that your freedos images are actually bootable without having to reboot your real machine (VMs boot a LOT faster than real systems). If they boot on the VM, they should boot on real hardware. – cas Jan 10 '18 at 00:20
  • I tried following your tutorial but got stuck, here's the problem: guy@guy-HP-Compaq-8200-Elite-SFF-PC ~ $ sudo mount -o loop,rw freedos-empty.img ./floppy [sudo] password for guy: mount: wrong fs type, bad option, bad superblock on /dev/loop4, missing codepage or helper program, or other error In some cases useful info is found in syslog - try dmesg | tail or so. – Guy D'Amico Jan 16 '18 at 20:14
  • guy@guy-HP-Compaq-8200-Elite-SFF-PC ~ $ dmesg | tail [16252.416302] UDF-fs: warning (device loop0): udf_load_vrs: No anchor found [16252.416304] UDF-fs: Rescanning with blocksize 2048 [16252.416513] UDF-fs: INFO Mounting volume 'CDROM', timestamp 2018/01/14 21:05 (1000) [16255.575589] loop1: [16461.774769] UDF-fs: warning (device loop2): udf_load_vrs: No anchor found – Guy D'Amico Jan 16 '18 at 20:15
  • [16461.774772] UDF-fs: Rescanning with blocksize 2048 [16461.774978] UDF-fs: INFO Mounting volume 'CDROM', timestamp 2018/01/14 21:05 (1000) [16464.353540] loop3: [17146.347119] UDF-fs: warning (device loop4): udf_fill_super: No partition found (2)[47193.112466] perf: interrupt took too long (3926 > 3925), lowering kernel.perf_event_max_sample_rate to 50750 – Guy D'Amico Jan 16 '18 at 20:15
  • why are you even trying that with a cd-rom image? you won't be able to write to it anyway. use an image file that has been formatted with FAT. – cas Jan 17 '18 at 01:51
  • e.g. use a copy of the "Boot Floppy" image (inside FD12FLOPPY.zip) from http://www.freedos.org/download/. Download it, unzip it, mount the FLOPPY.img inside it as noted above and **delete everything except command.com and kernel.sys**. then unmount the floppy image. that will give you a bare minimum bootable floppy image. you may want or need to customise it with DOS utilities, drivers, etc - use your CDROM image to install FD into a partition (or, better yet, a VM) and copy what you need from that. – cas Jan 17 '18 at 02:22
  • I should have identified this problem first I tried emailing you directly, that failed as well ;-( This command does not execute for me:"mkdir -p ./floppy". sudo mkdir -p ./floppy mkdir: cannot create directory ‘./floppy’: Read-only file system – Guy D'Amico Jan 18 '18 at 14:41