|
|
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):"
1.1.1.3 ! root 17: echo "- size: harddisk image size in megabytes, 8-512"
1.1 root 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
1.1.1.3 ! root 46: if [ $1 -gt 512 ]; then
! 47: echo "ERROR: mkdosfs supports Atari compatible partitions only up to 512 MB."
1.1 root 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=""
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.