From: Laurent.Clevy@meteo.fr Newsgroups: comp.sys.amiga.programmer, comp.sys.amiga.misc, comp.os.linux.misc Subject: Amiga floppy disks format (AmigaDos file system - floppies) Followup-To: poster Summary: This document describes the AmigaDos File System for floppy disks only. Physical/Logical formats, OFS/FFS, Directory caching, Links, Checksums. Archive-name: amiga/amiga_floppy_format Last-modified: 28. May 1997 Version: 0.9 Copyright: (c) 1997 Laurent Clevy Maintainer: Laurent Clevy FAQ : The Amiga floppy disks format Laurent Clevy Laurent.Clevy@meteo.fr 25 avenue Aristide Briand 28000 Chartres France Disclaimer and copyright ------------------------ This document is Copyright (C) 1997 by Laurent Clevy, but may be freely distributed, provided the author name and addresses are included and no money is charged for this document. This document is provided "as is". No warranties are made as to its correctness. Amiga, AmigaDos are registred trademarks of Gateway 2000. Introduction ------------ This document purpose is to describe the Amiga floppy disk format. I don't found any document which explains this format in details. Because I wish this machine to be supported a long time, including via emulators, I decided to write this file, and supply C routines as examples. Corrections (including about my english) are very welcome. Unfortunately, I have no permanent e-mail address currently, the only way to touch me is by postmail. Index ----- 1. How bytes are physically read/written on disk ? 1.1 What is MFM ? 1.2 What is the physical track format ? 1.3 What is the physical sector format ? 1.4 How to decode MFM data ? 2. What is the Amiga floppy disk geometry ? 3. How is logically organised a Amiga floppy disk ? 3.1 What is a Bootblock ? 3.2 What is a Rootblock ? 3.2.1 How to find the first sector of a entry ? 3.2.2 How to list directory entries ? 3.2.3 How to compute the checksum ? 3.3 How is managed the free/used blocks list ? 3.3.1 How to compute bitmap checksum ? 3.3.2 What is the 'bm_ext' field in Rootblock ? 3.4 How are stored files on a disk ? 3.5 How are stored directories ? 3.6 How are implemented links with AmigaDos ? 3.6.1 Hard links 3.6.2 Soft links 3.7 How is the block associated to directory caching ? 4. What is a blank disk ? 4.1 a Minimal blank disk 4.2 A 'Bootable' disk 4.3 A Directory cache mode disk 5. References 6. C Routines 7. Other Amiga file systems 8. To do Conventions ----------- * In this document, hexadecimal values are written like in C : for example 0x0c is the decimal value 12. As the Amiga is a 680x0 based computer, integers that require more than one byte are stored on disk in 'Motorola order' : the most significant byte comes first, then the less significant bytes in descending order of significance (MSB LSB for two-byte integers, B3 B2 B1 B0 for four-byte integers). A byte is 8 bits long. The left bit of a byte is the 7th, the right bit is the 0th. A 'word' is a 2 bytes (16 bits) integer, a 'long' a 4 bytes (32 bits) integer. Values are unsigned unless otherwise noted. * A block pointer is the number of this block on the disk. Disk starts with the #0 block. * Hashing is a method to access tables : given a number or a string, a hash function gives a index into a table. * Chained lists are cells oriented data structures. Each cell contains a pointer to the next or previous cell or both, the last pointer is null. C example : struct lcell { char name[10]; /* contains next cell adress, or NULL if this cell is the last */ struct lcell* next_cell; }; * Names of blocks begin with a capital (Rootblock). Name of fields are noted between quotes ('field_name'). * All formats are described as tables, one rows per field. Here is an example with then well known beginning of GIF format : offset type length name comments ---------------------------------------------------------- 0 char 3 signature 'GIF' 3 char 3 version '87a' or '89a' 6 short 1 screen width 8 short 1 screen height 1. How bytes are physically read/written on disk ? ================================================= Most of PC-like floppy disk controllers (FDC) are not able to read Amiga disks, because Amiga physical floppy disk operations are made by a specific chip called "Paula". However, i'm supplying this information because it's hard to find out. If you only want to understand the UAE .adf format, you don't need to read this part. For classical floppy disk operations, Paula is set with the following parameters : - MFM encoding - Precompensation time : 0 nanosec - Controller clock rate : 2 microseconds per bit cell - Sync value = 0x4489 The controller is able to put the read/write heads on a cylinder, and is able to read with the lower or upper side head. A track of 0x1900 words is usually read. 1.1 What is MFM ? ----------------- Because bits can't be written with magnetic fields directly on disk, an encoding scheme is required. Amiga floppy disks are MFM (Modified Frequence Modulation) encoded. The MFM encoding scheme is : user's data bit MFM coded bits --------------- -------------- 1 01 0 10 if following a 0 data bit 0 00 if following a 1 data bit User data longs are splitted in two parts, a part with even bits part first, followed by a part with odd bits. 1.2 What is the physical track format ? --------------------------------------- Double density (DD) disks have 11 sectors per track, High density (DD) disks have 22. So a track consists of 11/22 MFM encoded sectors, plus inter-track-gap. Note that sectors are not written from 0 to 10/21, you must use the 'info' field to recreate orderly track in memory. Each track begins with the first sector, and ends the end of the last sector (11th with DD disks, 22th with HDs). Each sector starts with 2 synchronization words. The synchro value is 0x4489. 1.3 What is the physical sector format ? ---------------------------------------- Here it comes : 0/0x0 word 2 MFM value 0xAAAA AAAA SYNCHRONIZATION 4/0x4 word 1 MFM value 0x4489 6/0x6 word 1 MFM value 0x4489 HEADER 8/0x8 long 1 info (even bits) 12/0xc long 1 info (odd bits) decoded long is : 0xff TT SS SG TT = track number ( 3 means cyl 1, head 1) SS = sector number ( 0 -> 10/21 ) sectors are not orderly !!! SG = number of sector before gap (including current one) Example for cylinder 0, head 1 of a DD disk : 0xff010009 0xff010108 0xff010207 0xff010306 0xff010405 0xff010504 0xff010603 0xff010702 0xff010801 <-- inter-sector-gap here ! 0xff01090b (0xb means -1 ?) 0xff010a0a (0xa means -2 ?) 16/0x10 long 4 sector label (even) 32/0x20 long 4 sector label (odd) decoded value seems to be always 0 END OF HEADER 48/0x30 long 1 header checksum (even) 52/0x34 long 1 header checksum (odd) (computed on mfm longs, longs between offsets 8 and 44 == 2*(1+4) longs) 56/0x38 long 1 data checksum (even) 60/0x3c long 1 data checksum (odd) (from 64 to 1088 == 2*512 longs) DATA 64/0x40 long 512 coded data (even) 576/240 long 512 coded data (odd) 1088/440 END OF DATA 1.4 How to decode MFM data ? ---------------------------- the algorithm : #define MASK 0x55555555 /* 01010101 ... 01010101 */ unsigned long *p1; /* MFM coded data buffer (size == 2*data_size) */ unsigned long *q; /* decoded data buffer (size == data_size) */ unsigned long a,b; unsigned long chksum; int data_size; /* size in long, 1 for info, 4 for sector label */ chksum=0L; do times { a = *p1; /* even bits */ b = *(p1+data_size); /* odd bits */ chksum^=a; /* eor */ chksum^=b; *q = ( b & MASK ) | ( ( a & MASK ) << 1 ); /* MFM decoding */ p1++; q++; } chksum&=MASK; 2. What is the Amiga floppy disk geometry ? =========================================== Here follows the disk geometries for DD and HD. bytes/sector sector/cyl sides/cyl cyl/disk ------------------------------------------------------------------------ DD disks 512 11 2 80 HD disks 512 22 2 80 The relations between sectors, sides and cylinders are for a DD disk : Block sector side track ----------------------------- 0 0 0 0 1 1 0 0 2 2 0 0 ... 10 10 0 0 11 0 1 0 ... 21 10 1 0 22 0 0 1 .. 1759 10 1 79 A DD disk has 11*2*80=1760 (0 to 1759) blocks, a HD disk has 22*2*80=3520 blocks. Of course the file system uses some of them, even for a blank disk. As the next part deals with, at least 4 blocks are used, for 3 logical structures : bootblock (2), rootblock (1) and bitmap block (1). The length of .ADF files for a DD disk is then 512*11*2*80 = 901120 bytes. 3. How is logically organised a Amiga floppy disk ? =================================================== The logical low level object of a Amiga disk is the 'sector' (or 'block') : 512 consecutive bytes. Disk information is distribued in the Bootblocks, the Rootblock and Bitmap block(s). FFS has block structures to provide directory list caching and (hard) links : Directory cache blocks and Link blocks. Directory tree is stored with a Directory block for each node. Directory entries (files, directories and links) are stored with a table, and are accessed with hashing and chained lists. Files are stored with a File header block and Data blocks. File extension blocks are also used for files stored with more than 72 Data blocks. 3.1 What is a Bootblock ? ------------------------- The first object of an Amiga floppy is the Boot block. If the checksum and the DiskType are correct, the system will execute the bootblock code, at boot time, of course :-). A valid bootblock is written by the AmigaDos command 'install'. * BootBlock (1024 bytes) sectors 0 and 1 ------------------------------------------------------------------------------- offset size number name meaning ------------------------------------------------------------------------------- 0/0 char 4 DiskType 'D''O''S' + flags (0->5) flags = set clr 0 FFS OFS 1 INT NOINT 2 DIRC NODIRC 4/4 long 1 Chksum special checksum 8/8 long 1 Rootblock ==880 DD and HD 12/0x0c char 1012 Bootblock code (see 4.2 'Bootable disk' for more information) ------------------------------------------------------------------------------- The DiskType flag informs of the disk format. OFS = Old/Original File System, the first one. (AmigaDos 1.2) FFS = Fast File System (AmigaDos 2.04) INT = International characters Mode (AmigaDos 3.0). DIRC = stands for Directory Cache Mode (AmigaDos 3.0). This mode speeds up directory listing, but take some disk space. There are few differences between the two file systems. - OFS Datablock stores 488 bytes, FFS stores 512 bytes, - FFS supports directories caching, links and international mode, - the FFS is faster than OFS. The bootblock checksum algorithm follows : * in 68000 assembler : lea bootbuffer,a0 move.l a0,a1 clr.l 4(a1) ;clear the checksum move.w #256-1,d1 ;1024/4 times moveq #0,d0 lpchk: add.l (a0)+,d0 ;accumulation bcc.s jump ;if carry set, add 1 to checksum add.l #1,d0 jump: dbf d1,lpchk ;next long word not.l d0 move.l d0,4(a1) ;new checksum * in C : #include #define Short(p) ((p)[0]<<8 | (p)[1]) #define Long(p) (Short(p)<<16 | Short(p+2)) unsigned long newsum,d; unsigned char buf[1024]; /* contains bootblock */ int i; memset(buf+4,0,4); /* clear old checksum */ newsum=0L; for(i=0; i<256; i++) { d=Long(buf+i*4); if ( (ULONG_MAX-newsum) < d ) /* overflow */ newsum++; newsum+=d; } newsum=~newsum; 3.2 What is a Rootblock ? ------------------------- The Rootblock is at the middle of the media : block number 880 for DD disks, block 1760 for HDs. The Rootblock contains information about disk : its name, its formatting date, etc ... It also contains information to access the files/directories/links located at the root (Unix /) directory. * Rootblock (512 bytes) sector 880 for a DD disk, 1760 for a HD disk ------------------------------------------------------------------------------ 0/0 long 1 type block primary type = T_HEADER (value 2) 4/4 long 1 header_key unused in rootblock (value 0) long 1 high_seq unused (value 0) 12/c long 1 ht_size Hash table size in long (value 0x48) 16/10 long 1 first_data unused (value 0) 20/14 long 1 chksum sum to check block integrity 24/18 long 72 ht[] hash table (entry block number) 312/138 long 1 bm_flag bitmap flag, -1 means VALID 316/13c long 25 bm_pages[] bitmap blocks pointers (first at 0) 416/1a0 long 1 bm_ext first bitmap extension block (Hard disks only) ... 432/1b0 char 1 name_len; disk name length 433/1b1 char 30 diskname[] disk name ... 472/1d8 long 1 days last access date : days since 1 jan 1978 476/1dc long 1 mins minutes past midnight 480/1e0 long 1 ticks ticks (1/50 sec) past last minute 484/1e4 long 1 c_days creation date 488/1e8 long 1 c_mins 492/1ec long 1 c_ticks long 1 next_hash unused (value = 0) long 1 parent_dir unused (value = 0) 504/1f8 long 1 extension FFS: first directory cache block, 0 otherwise 508/1fc long 1 sec_type block secondary type = ST_ROOT (value 1) ------------------------------------------------------------------------------- 3.2.1 How to find the first sector of a directory entry ? --------------------------------------------------------- Given the name of a file/directory/link you compute its hash value with this algorithm : * The hash function : #include int HashName(char *name) { int hash; int i,l; l=hash=strlen(name); for(i=0; i