Annotation of hatari/tools/atari-hd-image.sh, revision 1.1.1.2

1.1       root        1: #!/bin/sh
1.1.1.2 ! root        2: # script for creating a compatible DOS HD image for Hatari with
        !             3: # a single FAT16 partition of given size, with given contents
1.1       root        4: 
                      5: # defaults for disk attributes
                      6: diskfile=hd.img   # HD image filename
                      7: partname=DOS      # partition name
                      8: 
1.1.1.2 ! root        9: # no args or first arg has non-digit characters?
        !            10: if [ $# -lt 1 ] || [ \! -z "$(echo $1|tr -d 0-9)" ]; then
1.1       root       11:        name=${0##*/}
                     12:        echo
                     13:        echo "usage: $name <size> [filename] [partition name] [directory]"
                     14:        echo
                     15:        echo "Create an ACSI/IDE harddisk image for Hatari with a single Atari"
                     16:        echo "compatible DOS partition.  Arguments are (defaults in parenthesis):"
                     17:        echo "- size: harddisk image size in megabytes, 8-256"
                     18:        echo "- filename: name for the harddisk image ($diskfile)"
                     19:        echo "- partition name: name for that single partition ($partname)"
                     20:        echo "- directory: directory for initial content copied to the image"
                     21:        echo
                     22:        echo "For example:"
                     23:        echo "- 16MB '$diskfile' HD image:"
                     24:        echo "  $name 16"
                     25:        echo "-  8MB image with 'TEST' partition having files from content/:"
                     26:        echo "  $name 8 8mb-disk.img TEST content/"
                     27:        echo
                     28:        exit 1
                     29: fi
                     30: 
                     31: # sfdisk/mkdosfs reside in /sbin
                     32: PATH=/sbin:$PATH
                     33: export PATH
                     34: 
                     35: # check tools
1.1.1.2 ! root       36: if [ -z $(which mkdosfs) ] || [ -z $(which python) ]; then
        !            37:        echo "ERROR: either mkdosfs or python tool missing!"
1.1       root       38:        exit 1
                     39: fi
                     40: 
                     41: # check disk size
                     42: if [ $1 -lt 5 ]; then
                     43:        echo "ERROR: disk size needs to be at least 5 (MB) to work properly."
                     44:        exit 1
                     45: fi
                     46: if [ $1 -gt 256 ]; then
                     47:        echo "ERROR: EmuTOS supports only partitions up to 256 (MB)."
                     48:        exit 1
                     49: fi
1.1.1.2 ! root       50: 
1.1       root       51: # disk geometry
1.1.1.2 ! root       52: skip=0            # alignment / "padding" sectors between MBR before partition
1.1       root       53: diskheads=16
1.1.1.2 ! root       54: tracksectors=32          # same as used by mkdosfs
1.1       root       55: sectorsize=512
                     56: 
1.1.1.2 ! root       57: # partition size in sectors:
        !            58: # 16*32*512 is 1/4MB -> multiply by 4 to get number of required sectors
        !            59: partsectors=$((4*$1*$diskheads*$tracksectors))
1.1       root       60: 
                     61: # check optional arguments
                     62: if [ \! -z $2 ]; then
                     63:        diskfile=$2
                     64: fi
                     65: if [ \! -z $3 ]; then
                     66:        partname=$3
                     67: fi
                     68: if [ \! -z $4 ]; then
                     69:        if [ -z $(which mcopy) ]; then
                     70:                echo "ERROR: mcopy (from Mtools) missing!"
                     71:                exit 1
                     72:        fi
                     73:        contentdir=$4
                     74: fi
                     75: 
                     76: # don't overwrite files by accident
                     77: if [ -f $diskfile ]; then
                     78:        echo "ERROR: given harddisk image already exits. Give another name or remove it:"
                     79:        echo "  rm $diskfile"
                     80:        exit 1
                     81: fi
                     82: 
                     83: # temporary files
                     84: tmppart=$diskfile.part
                     85: 
1.1.1.2 ! root       86: error="premature script exit"
1.1       root       87: # script exit/error handling
                     88: exit_cleanup ()
                     89: {
                     90:        echo
1.1.1.2 ! root       91:        if [ -z "$error" ]; then
1.1       root       92:                echo "$step) Cleaning up..."
                     93:        else
1.1.1.2 ! root       94:                echo "ERROR: $error"
1.1       root       95:                echo
1.1.1.2 ! root       96:                echo "cleaning up..."
1.1       root       97:                echo "rm -f $diskfile"
                     98:                rm -f $diskfile
                     99:        fi
                    100:        echo "rm -f $tmppart"
                    101:        rm -f $tmppart
                    102:        echo "Done."
                    103: }
                    104: trap exit_cleanup EXIT
                    105: 
                    106: echo
                    107: step=1
1.1.1.2 ! root      108: echo "$step) Creating DOS Master Boot Record / partition table..."
        !           109: # See:
        !           110: # - http://en.wikipedia.org/wiki/Master_boot_record
        !           111: # - http://en.wikipedia.org/wiki/Cylinder-head-sector
        !           112: # - http://en.wikipedia.org/wiki/File_Allocation_Table#Boot_Sector
        !           113: # For DOS MBR, the values are little endian.
        !           114: # -----------
        !           115: python << EOF
        !           116: #!/usr/bin/env python
        !           117: mbr = bytearray(512)
        !           118: 
        !           119: def set_long(idx, value):
        !           120:     mbr[idx+0] = value & 0xff
        !           121:     mbr[idx+1] = value >> 8 & 0xff
        !           122:     mbr[idx+2] = value >> 16 & 0xff
        !           123:     mbr[idx+3] = value >> 24
        !           124: 
        !           125: def set_word(idx, value):
        !           126:     mbr[idx] = value & 0xff
        !           127:     mbr[idx+1] = value >> 8 & 0xff
        !           128: 
        !           129: def set_CHS(idx, values):
        !           130:     c, h, s = values
        !           131:     print "CHS: %3d,%3d,%3d @ $%x" % (c,h,s,idx)
        !           132:     mbr[idx] = h
        !           133:     mbr[idx+1] = (s & 0x3F) | ((c >> 2) & 0xC0)
        !           134:     mbr[idx+2] = c & 0xFF
        !           135: 
        !           136: def LBA2CHS(lba):
        !           137:     c = lba / ($tracksectors * $diskheads)
        !           138:     h = (lba / $tracksectors) % $diskheads
        !           139:     s = (lba % $tracksectors) + 1
        !           140:     return (c,h,s)
        !           141: 
        !           142: # disk size
        !           143: sectors = 1 + $skip + $partsectors
        !           144: if sectors < 65536:
        !           145:     set_word(0x13, sectors)
        !           146:     set_long(0x20, sectors)
        !           147:     parttype=0x4
        !           148: else:
        !           149:     set_long(0x20, sectors)
        !           150:     parttype=0x6
        !           151: 
        !           152: # reserved sectors = MBR
        !           153: mbr[0x0E] = 1
        !           154: 
        !           155: # CHS information
        !           156: set_word(0x0B, $sectorsize)
        !           157: mbr[0x0D] = 2 # sectors / cluster
        !           158: set_word(0x18, $tracksectors)
        !           159: set_word(0x1A, $diskheads)
        !           160:   
        !           161: # non-removable disk
        !           162: mbr[0x15] = 0xF8
        !           163: mbr[0x24] = 0x80
        !           164: 
        !           165: # partition size in sectors
        !           166: partsectors = $partsectors - 1
        !           167: # first partition takes all
        !           168: offset = 0x1BE
        !           169: mbr[offset] = 0x80 # bootable
        !           170: mbr[offset+4] = parttype
        !           171: # partition start & sector count in LBA
        !           172: set_long(offset + 0x08, 1)
        !           173: set_long(offset + 0x0C, partsectors)
        !           174: # partition start & end in CHS
        !           175: set_CHS(offset + 1, LBA2CHS(1))
        !           176: set_CHS(offset + 5, LBA2CHS(partsectors))
        !           177: # 3 last partitions are empty
        !           178: for i in (1,2,3):
        !           179:     offset += 0x10
        !           180:     set_long(offset + 0x08, partsectors+1)
        !           181:     set_long(offset + 0x0C, 0)
        !           182:     set_CHS(offset + 1, LBA2CHS(partsectors+1))
        !           183:     set_CHS(offset + 5, LBA2CHS(partsectors))
        !           184: 
        !           185: # MBR signature
        !           186: mbr[0x1FE] = 0x55
        !           187: mbr[0x1FF] = 0xAA
1.1       root      188: 
1.1.1.2 ! root      189: open("$diskfile", "wb").write(bytes(mbr))
1.1       root      190: EOF
1.1.1.2 ! root      191: # -----------
        !           192: od -t x1 $diskfile
1.1       root      193: 
                    194: echo
                    195: step=$(($step+1))
1.1.1.2 ! root      196: echo "$step) Creating an Atari TOS compatible DOS partition..."
1.1       root      197: # mkdosfs keeps the sector count below 32765 when -A is used by increasing
                    198: # the logical sector size (this is for TOS compatibility, -A guarantees
                    199: # also 2 sectors / cluster and Atari serial number etc).  Mtools barfs
                    200: # if partition size doesn't divide evenly with its track size.  Determine
                    201: # suitable cluster count & corresponding track size and align (decrease)
                    202: # the file system sector count accordingly.
                    203: tracksize=32
1.1.1.2 ! root      204: clustertmp=$((partsectors/2))
        !           205: echo "Sectors: $partsectors, sectors/track: $tracksize, clusters: $clustertmp"
1.1       root      206: while [ $clustertmp -gt 32765 ]; do
                    207:        clustertmp=$((clustertmp/2))
                    208:        tracksize=$(($tracksize*2))
                    209:        echo "Doubling sector size as >32765 clusters -> $clustertmp clusters"
                    210: done
1.1.1.2 ! root      211: sectors=$(($partsectors/$tracksize))
1.1       root      212: sectors=$(($sectors*$tracksize))
                    213: kilobytes=$(($sectors/2))
1.1.1.2 ! root      214: if [ $sectors -ne $partsectors ]; then
        !           215:        echo "Align sector count with clusters/sectors/track: $partsectors -> $sectors ($kilobytes kB)"
1.1       root      216: fi
1.1.1.2 ! root      217: echo "mkdosfs -A -F 16 -n $partname -C $tmppart $kilobytes"
        !           218: mkdosfs -A -F 16 -n $partname -C $tmppart $kilobytes
1.1       root      219: 
                    220: if [ \! -z $contentdir ]; then
                    221:        echo
                    222:        step=$(($step+1))
                    223:        # copy contents of given directory to the new partition
                    224:        echo "$step) Copying the initial content to the partition..."
                    225:        echo "MTOOLS_NO_VFAT=1 mcopy -i $tmppart -spmv $contentdir/* ::"
                    226:        MTOOLS_NO_VFAT=1 mcopy -i $tmppart -spmv $contentdir/* ::
                    227:        if [ $? -ne 0 ]; then
1.1.1.2 ! root      228:                error="mcopy failed."
1.1       root      229:                exit 2
                    230:        fi
                    231: fi
                    232: 
                    233: echo
                    234: step=$(($step+1))
                    235: # copy the partition into disk
                    236: echo "$step) Copying the partition to disk image..."
1.1.1.2 ! root      237: echo "dd if=$tmppart of=$diskfile bs=512 seek=$((1+$skip)) count=$sectors"
        !           238: dd if=$tmppart of=$diskfile bs=512 seek=$((1+$skip)) count=$sectors
1.1       root      239: 
                    240: step=$(($step+1))
                    241: # cleanup is done by exit_cleanup() trap
1.1.1.2 ! root      242: error=""

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.