.\" Believe it or not, reportedly there are nroffs which do not know \(en .if n .ds en - .if t .ds en \(en .TH CPM 5 "November 26, 2007" "CP/M tools" "File formats" .SH NAME \"{{{roff}}}\"{{{ cpm \- CP/M disk and file system format .\"}}} .SH DESCRIPTION \"{{{ .SS "Characteristic sizes" \"{{{ Each CP/M disk format is described by the following specific sizes: .RS .sp Sector size in bytes .br Number of tracks .br Number of sectors .br Block size .br Number of directory entries .br Logical sector skew .br Number of reserved system tracks .sp .RE A block is the smallest allocatable storage unit. CP/M supports block sizes of 1024, 2048, 4096, 8192 and 16384 bytes. Unfortunately, this format specification is not stored on the disk and there are lots of formats. Accessing a block is performed by accessing its sectors, which are stored with the given software skew. .\"}}} .SS "Device areas" \"{{{ A CP/M disk contains three areas: .RS .sp System tracks (optional) .br Directory .br Data .sp .RE The system tracks store the boot loader and CP/M itself. In order to save disk space, there are non-bootable formats which omit those system tracks. The term \fIdisk capacity\fP always excludes the space for system tracks. Note that there is no bitmap or list for free blocks. When accessing a drive for the first time, CP/M builds this bitmap in core from the directory. .\"}}} .SS "Directory entries" \"{{{ The directory is a sequence of directory entries (also called extents), which contain 32 bytes of the following structure: .RS .sp .ta 3n 6n 9n 12n 15n 18n 21n 24n 27n 30n 33n 36n 39n 42n 45n St F0 F1 F2 F3 F4 F5 F6 F7 E0 E1 E2 Xl Bc Xh Rc .br Al Al Al Al Al Al Al Al Al Al Al Al Al Al Al Al .sp .RE .\"{{{ St = status \fBSt\fP is the status; possible values are: .RS .sp 0\*(en15: used for file, status is the user number .br 16\*(en31: used for file, status is the user number (P2DOS) or used for password extent (CP/M 3 or higher) .br 32: disc label .br 33: time stamp (P2DOS) .br 0xE5: unused .sp .RE .\"}}} .LP .\"{{{ F0-E2 = file name and extension \fBF0\*(enE2\fP are the file name and its extension. They may consist of any printable 7 bit ASCII character but: \fB< > . , ; : = ? * [ ]\fP. The file name must not be empty, the extension may be empty. Both are padded with blanks. The highest bit of each character of the file name and extension is used as attribute. The attributes have the following meaning: .RS .sp F0: requires set wheel byte (Backgrounder II) .br F1: public file (P2DOS, ZSDOS), forground-only command (Backgrounder II) .br F2: date stamp (ZSDOS), background-only commands (Backgrounder II) .br F7: wheel protect (ZSDOS) .br E0: read-only .br E1: system file .br E2: archived .sp .RE Public files (visible under each user number) are not supported by CP/M 2.2, but there is a patch and some free CP/M clones support them without any patches. .LP The wheel byte is (by default) the memory location at 0x4b. If it is zero, only non-privileged commands may be executed. .\"}}} .LP .\"{{{ Xl, Xh = extent number \fBXl\fP and \fBXh\fP store the extent number. A file may use more than one directory entry, if it contains more blocks than an extent can hold. In this case, more extents are allocated and each of them is numbered sequentially with an extent number. If a physical extent stores more than 16k, it is considered to contain multiple logical extents, each pointing to 16k data, and the extent number of the last used logical extent is stored. Note: Some formats decided to always store only one logical extent in a physical extent, thus wasting extent space. CP/M 2.2 allows 512 extents per file, CP/M 3 and higher allow up to 2048. Bit 5\*(en7 of Xl are 0, bit 0\*(en4 store the lower bits of the extent number. Bit 6 and 7 of Xh are 0, bit 0\*(en5 store the higher bits of the extent number. .\"}}} .LP .\"{{{ Rc, Bc = record count, byte count \fBRc\fP and \fBBc\fP determine the length of the data used by this extent. The physical extent is divided into logical extents, each of them being 16k in size (a physical extent must hold at least one logical extent, e.g. a blocksize of 1024 byte with two-byte block pointers is not allowed). Rc stores the number of 128 byte records of the last used logical extent. Bc stores the number of bytes in the last used record. The value 0 means 128 for backward compatibility with CP/M 2.2, which did not support Bc. .\"}}} .LP .\"{{{ Al = allocated blocks \fBAl\fP stores block pointers. If the disk capacity is less than 256 blocks, Al is interpreted as 16 byte-values, otherwise as 8 double-byte-values. A block pointer of 0 marks a hole in the file. If a hole covers the range of a full extent, the extent will not be allocated. In particular, the first extent of a file does not neccessarily have extent number 0. A file may not share blocks with other files, as its blocks would be freed if the other files is erased without a following disk system reset. CP/M returns EOF when it reaches a hole, whereas UNIX returns zero-value bytes, which makes holes invisible. .\"}}} .\"}}} .SS "Time stamps" \"{{{ P2DOS and CP/M Plus support time stamps, which are stored in each fourth directory entry. This entry contains the time stamps for the extents using the previous three directory entries. Note that you really have time stamps for each extent, no matter if it is the first extent of a file or not. The structure of time stamp entries is: .RS .sp 1 byte status 0x21 .br 8 bytes time stamp for third-last directory entry .br 2 bytes unused .br 8 bytes time stamp for second-last directory entry .br 2 bytes unused .br 8 bytes time stamp for last directory entry .sp .RE A time stamp consists of two dates: Creation and modification date (the latter being recorded when the file is closed). CP/M Plus further allows optionally to record the access instead of creation date as first time stamp. .RS .sp 2 bytes (little-endian) days starting with 1 at 01-01-1978 .br 1 byte hour in BCD format .br 1 byte minute in BCD format .sp .RE .\"}}} .SS "Disc labels" \"{{{ CP/M Plus support disc labels, which are stored in an arbitrary directory entry. The structure of disc labels is: .RS .sp 1 byte status 0x20 .br \fBF0\*(enE2\fP are the disc label .br 1 byte mode: bit 7 activates password protection, bit 6 causes time stamps on access, but 5 causes time stamps on modifications, bit 4 causes time stamps on creation and bit 0 is set when a label exists. Bit 4 and 6 are exclusively set. .br 1 byte password decode byte: To decode the password, xor this byte with the password bytes in reverse order. To encode a password, add its characters to get the decode byte. .br 2 reserved bytes .br 8 password bytes .br 4 bytes label creation time stamp .br 4 bytes label modification time stamp .sp .RE .\"}}} .SS "Passwords" \"{{{ CP/M Plus supports passwords, which are stored in an arbitrary directory entry. The structure of these entries is: .RS .sp 1 byte status (user number plus 16) .br \fBF0\*(enE2\fP are the file name and its extension. .br 1 byte password mode: bit 7 means password required for reading, bit 6 for writing and bit 5 for deleting. .br 1 byte password decode byte: To decode the password, xor this byte with the password bytes in reverse order. To encode a password, add its characters to get the decode byte. .br 2 reserved bytes .br 8 password bytes .sp .RE .\"}}} .\"}}} .SH "SEE ALSO" \"{{{ .IR mkfs.cpm (1), .IR fsck.cpm (1), .IR fsed.cpm (1), .IR cpmls (1) .\"}}}