|
| 1 | +.\" Believe it or not, reportedly there are nroffs which do not know \(en |
| 2 | +.if n .ds en - |
| 3 | +.if t .ds en \(en |
| 4 | +.TH CPM 5 "July 2, 1997" "CP/M tools" "File formats" |
| 5 | +.SH NAME \"{{{roff}}}\"{{{ |
| 6 | +cpm \- CP/M disk and file system format |
| 7 | +.\"}}} |
| 8 | +.SH DESCRIPTION \"{{{ |
| 9 | +.SS "Characteristic sizes" \"{{{ |
| 10 | +Each CP/M disk format is described by the following specific sizes: |
| 11 | +.RS |
| 12 | +.sp |
| 13 | +Sector size in bytes |
| 14 | +.br |
| 15 | +Number of tracks |
| 16 | +.br |
| 17 | +Number of sectors |
| 18 | +.br |
| 19 | +Block size |
| 20 | +.br |
| 21 | +Number of directory entries |
| 22 | +.br |
| 23 | +Logical sector skew |
| 24 | +.br |
| 25 | +Number of reserved system tracks |
| 26 | +.sp |
| 27 | +.RE |
| 28 | +A block is the smallest allocatable storage unit. CP/M supports block |
| 29 | +sizes of 1024, 2048, 4096, 8192 and 16384 bytes. Unfortunately, this |
| 30 | +format specification is not stored on the disk and there are lots of |
| 31 | +formats. Accessing a block is performed by accessing its sectors, which |
| 32 | +are stored with the given software skew. |
| 33 | +.\"}}} |
| 34 | +.SS "Device areas" \"{{{ |
| 35 | +A CP/M disk contains three areas: |
| 36 | +.RS |
| 37 | +.sp |
| 38 | +System tracks (optional) |
| 39 | +.br |
| 40 | +Directory |
| 41 | +.br |
| 42 | +Data |
| 43 | +.sp |
| 44 | +.RE |
| 45 | +The system tracks store the boot loader and CP/M itself. In order to save |
| 46 | +disk space, there are non-bootable formats which omit those system tracks. |
| 47 | +The term \fIdisk capacity\fP always excludes the space for system tracks. |
| 48 | +Note that there is no bitmap or list for free blocks. When accessing a |
| 49 | +drive for the first time, CP/M builds this bitmap in core from the directory. |
| 50 | +.\"}}} |
| 51 | +.SS "Directory entries" \"{{{ |
| 52 | +The directory is a sequence of directory entries (also called extents), |
| 53 | +which contain 32 bytes of the following structure: |
| 54 | +.RS |
| 55 | +.sp |
| 56 | +.ta 3n 6n 9n 12n 15n 18n 21n 24n 27n 30n 33n 36n 39n 42n 45n |
| 57 | +St F0 F1 F2 F3 F4 F5 F6 F7 E0 E1 E2 Xl Bc Xh Rc |
| 58 | +.br |
| 59 | +Al Al Al Al Al Al Al Al Al Al Al Al Al Al Al Al |
| 60 | +.sp |
| 61 | +.RE |
| 62 | +.\"{{{ St = status |
| 63 | +\fBSt\fP is the status; possible values are: |
| 64 | +.RS |
| 65 | +.sp |
| 66 | +0\*(en15: used for file, status is the user number |
| 67 | +.br |
| 68 | +16\*(en31: used for file, status is the user number (P2DOS) |
| 69 | +or used for password extent (CP/M 3 or higher) |
| 70 | +.br |
| 71 | +32: disc label |
| 72 | +.br |
| 73 | +33: time stamp (P2DOS) |
| 74 | +.br |
| 75 | +0xE5: unused |
| 76 | +.sp |
| 77 | +.RE |
| 78 | +.\"}}} |
| 79 | +.LP |
| 80 | +.\"{{{ F0-E2 = file name and extension |
| 81 | +\fBF0\*(enE2\fP are the file name and its extension. They may consist of |
| 82 | +any printable 7 bit ASCII character but: \fB< > . , ; : = ? * [ ]\fP. |
| 83 | +The file name must not be empty, the extension may be empty. Both are |
| 84 | +padded with blanks. The highest bit of each character of the file name |
| 85 | +and extension is used as attribute. The attributes have the following |
| 86 | +meaning: |
| 87 | +.RS |
| 88 | +.sp |
| 89 | +F0: requires set wheel byte (Backgrounder II) |
| 90 | +.br |
| 91 | +F1: public file (P2DOS, ZSDOS), forground-only command (Backgrounder II) |
| 92 | +.br |
| 93 | +F2: date stamp (ZSDOS), background-only commands (Backgrounder II) |
| 94 | +.br |
| 95 | +F7: wheel protect (ZSDOS) |
| 96 | +.br |
| 97 | +E0: read-only |
| 98 | +.br |
| 99 | +E1: system file |
| 100 | +.br |
| 101 | +E2: archived |
| 102 | +.sp |
| 103 | +.RE |
| 104 | +Public files (visible under each user number) are not supported by CP/M |
| 105 | +2.2, but there is a patch and some free CP/M clones support them without |
| 106 | +any patches. |
| 107 | +.LP |
| 108 | +The wheel byte is (by default) the memory location at 0x4b. If it is |
| 109 | +zero, only non-privileged commands may be executed. |
| 110 | +.\"}}} |
| 111 | +.LP |
| 112 | +.\"{{{ Xl, Xh = extent number |
| 113 | +\fBXl\fP and \fBXh\fP store the extent number. |
| 114 | +A file may use more than one directory entry, if it contains more blocks |
| 115 | +than an extent can hold. In this case, more extents are allocated and each |
| 116 | +of them is numbered sequentially with an extent number. If a physical |
| 117 | +extent stores more than one logical extent, the extent number of the |
| 118 | +last used logical extent is stored. |
| 119 | +CP/M 2.2 allows 512 extents per file, CP/M 3 and higher allow up to 2048. |
| 120 | +Bit 5\*(en7 of Xl are 0, bit 0\*(en4 store the lower bits of the |
| 121 | +extent number. Bit 6 and 7 of Xh are 0, bit 0\*(en5 store the higher bits of |
| 122 | +the extent number. |
| 123 | +.\"}}} |
| 124 | +.LP |
| 125 | +.\"{{{ Rc, Bc = record count, byte count |
| 126 | +\fBRc\fP and \fBBc\fP determine the length of the data used by this extent. The |
| 127 | +physical extent is divided into logical extents, each of them being 16k |
| 128 | +in size (a physical extent must hold at least one logical extent, e.g. a |
| 129 | +blocksize of 1024 byte with two-byte block pointers is not allowed). |
| 130 | +Rc stores the number of 128 byte records of the last used logical extent. |
| 131 | +Bc stores the number of bytes in the last used record. The value 0 means |
| 132 | +128 for backward compatibility with CP/M 2.2, which did not support Bc. |
| 133 | +.\"}}} |
| 134 | +.LP |
| 135 | +.\"{{{ Al = allocated blocks |
| 136 | +\fBAl\fP stores block pointers. If the disk capacity is less than 256 blocks, |
| 137 | +Al is interpreted as 16 byte-values, otherwise as 8 double-byte-values. |
| 138 | +A block pointer of 0 marks a hole in the file. If a hole |
| 139 | +covers the range of a full extent, the extent will not be allocated. In particular, |
| 140 | +the first extent of a file does not neccessarily have extent number 0. |
| 141 | +A file may not share blocks with other files, as its blocks would be freed |
| 142 | +if the other files is erased without a following disk system reset. |
| 143 | +.\"}}} |
| 144 | +.\"}}} |
| 145 | +.SS "Time stamps" \"{{{ |
| 146 | +P2DOS and CP/M Plus support time stamps, which are stored in each fourth |
| 147 | +directory entry. This entry contains the time stamps for |
| 148 | +the extents using the previous three directory entries. Note that you |
| 149 | +really have time stamps for each extent, no matter if it is the first |
| 150 | +extent of a file or not. The structure of time stamp entries is: |
| 151 | +.RS |
| 152 | +.sp |
| 153 | +1 byte status 0x21 |
| 154 | +.br |
| 155 | +8 bytes time stamp for third-last directory entry |
| 156 | +.br |
| 157 | +2 bytes unused |
| 158 | +.br |
| 159 | +8 bytes time stamp for second-last directory entry |
| 160 | +.br |
| 161 | +2 bytes unused |
| 162 | +.br |
| 163 | +8 bytes time stamp for last directory entry |
| 164 | +.sp |
| 165 | +.RE |
| 166 | +A time stamp consists of two dates: Creation and modification date (the |
| 167 | +latter being recorded when the file is closed). CP/M Plus further |
| 168 | +allows optionally to record the access instead of creation date as first |
| 169 | +time stamp. |
| 170 | +.RS |
| 171 | +.sp |
| 172 | +2 bytes (little-endian) days starting with 1 at 01-01-1978 |
| 173 | +.br |
| 174 | +1 byte hour in BCD format |
| 175 | +.br |
| 176 | +1 byte minute in BCD format |
| 177 | +.sp |
| 178 | +.RE |
| 179 | +.\"}}} |
| 180 | +.SS "Disc labels" \"{{{ |
| 181 | +CP/M Plus support disc labels, which are stored in an arbitrary directory |
| 182 | +entry. |
| 183 | +The structure of disc labels is: |
| 184 | +.RS |
| 185 | +.sp |
| 186 | +1 byte status 0x20 |
| 187 | +.br |
| 188 | +\fBF0\*(enE2\fP are the disc label |
| 189 | +.br |
| 190 | +1 byte mode: bit 7 activates password protection, bit 6 causes time stamps on |
| 191 | +access, but 5 causes time stamps on modifications, bit 4 causes time stamps on |
| 192 | +creation and bit 0 is set when a label exists. Bit 4 and 6 are exclusively set. |
| 193 | +.br |
| 194 | +1 byte password decode byte: To decode the password, xor this byte with the password |
| 195 | +bytes in reverse order. To encode a password, add its characters to get the |
| 196 | +decode byte. |
| 197 | +.br |
| 198 | +2 reserved bytes |
| 199 | +.br |
| 200 | +8 password bytes |
| 201 | +.br |
| 202 | +4 bytes label creation time stamp |
| 203 | +.br |
| 204 | +4 bytes label modification time stamp |
| 205 | +.sp |
| 206 | +.RE |
| 207 | +.\"}}} |
| 208 | +.SS "Passwords" \"{{{ |
| 209 | +CP/M Plus supports passwords, which are stored in an arbitrary directory |
| 210 | +entry. |
| 211 | +The structure of these entries is: |
| 212 | +.RS |
| 213 | +.sp |
| 214 | +1 byte status (user number plus 16) |
| 215 | +.br |
| 216 | +\fBF0\*(enE2\fP are the file name and its extension. |
| 217 | +.br |
| 218 | +1 byte password mode: bit 7 means password required for reading, bit 6 for writing |
| 219 | +and bit 5 for deleting. |
| 220 | +.br |
| 221 | +1 byte password decode byte: To decode the password, xor this byte with the password |
| 222 | +bytes in reverse order. To encode a password, add its characters to get the |
| 223 | +decode byte. |
| 224 | +.br |
| 225 | +2 reserved bytes |
| 226 | +.br |
| 227 | +8 password bytes |
| 228 | +.sp |
| 229 | +.RE |
| 230 | +.\"}}} |
| 231 | +.\"}}} |
| 232 | +.SH "SEE ALSO" \"{{{ |
| 233 | +.IR mkfs.cpm (1), |
| 234 | +.IR fsck.cpm (1), |
| 235 | +.IR fsed.cpm (1), |
| 236 | +.IR cpmls (1) |
| 237 | +.\"}}} |
0 commit comments