koster@cory.Berkeley.EDU (Kevin Oster) (06/09/88)
This is a very technical question. I am going to the disk hardware directly (Thanks for all the help on getting that going...It was the disk.resource that solved it.) Anyway, I want to write a format routine and I don't know enough about the checksum. The RKM volume 2 tells a little about the format. It says there are two 32 bit checksums, one for the header information and one for the data area. How do I compute them? These checksums are on the raw data after MFM decoding, even lower level than trackdisk. Also is there anything special about the $4489 matchword? Couldn't it be found by chance in a sector's data area? ($4489 is the MFM encoded version of $A1)
carolyn@cbmvax.UUCP (Carolyn Scheppner CATS) (06/10/88)
In article <3845@pasteur.Berkeley.Edu> koster@cory.Berkeley.EDU.UUCP (Kevin Oster) writes: > > This is a very technical question. I am going to the disk hardware directly >(Thanks for all the help on getting that going...It was the disk.resource that >solved it.) Anyway, I want to write a format routine and I don't know enough >about the checksum. Here's some info from an AmigaMail article. It may contain what you need. Notes on 1.2 Amiga Trackdisk Format =================================== Copyright 1987 Commodore-Amiga, Inc. The following notes provide some detailed information on the format of a 3 1/2" floppy under the current AmigaDOS 1.2 filing system. These notes are for informational purposes only and relate only to the layout under the current filing system. The structures and layout are private, and are subject to change in the future. In other words, if you write your own Format code, or use any part of these structures or blocks for your own purposes, or make any other assumptions based on the current layout, there is a good chance that you will be incompatible with any future filing system enhancements, because future enhancements may support additional formats and may use some of the currently unused areas in the reserved blocks. Other information about the current disk layout can be found in the Amiga manuals. The format of directory, file header, file list, and data blocks is discussed in the AmigaDOS Manual (Bantam). A description of Amiga MFM encoding can be found on pages C9-C10 of the ROM Kernel "Exec" manual (Addison-Wesley). 1) ROOT BLOCK The Root block is normally in the middle of the disk (halfway through blocks). On the 3 1/2" floppy, this is block 880 (track 40, sector 0, first surface). /* Rootblock structure (private) * Copyright (c) 1985 Commodore-Amiga Inc. All Rights Reserved */ #define WORDSPERBLOCK 128 /* NOTE - WORDS means LONGWORDS (BCPLese) */ #define HASHSIZE (WORDSPERBLOCK - 56) #define NUMBMPAGES 26 struct RootBlock { ULONG rb_Type; /* type */ ULONG rb_HeaderKey; /* header key (always zero) */ ULONG rb_HighSeqNum; /* highest sequence number (always 0) */ ULONG rb_HashSize; /* hash size (= BLOCKSIZE-56)*/ ULONG rb_Reserved; /* reserved */ ULONG rb_CheckSum; /* checksum */ ULONG rb_HashTable[HASHSIZE]; /* hash table */ ULONG rb_BMFlag; /* TRUE if Bitmap on disk is valid */ ULONG rb_BitMapPages[NUMBMPAGES]; /* indicates blocks containing bitmap */ struct DateStamp rb_LastDate; /* volume last altered date and time */ UBYTE rb_DiskName[13*4]; /* volume name BCPL string <= 30 chars*/ struct DateStamp rb_CreateDate; /* volume creation date and time */ ULONG rb_HashChain; /* next entry on this hash chain (always zero)*/ ULONG rb_Parent; /* parent directory (always zero) */ ULONG rb_Extension; /* extension (always zero) */ ULONG rb_SecondaryType; /* secondary type indicates root block*/ }; When an Amiga 3 1/2" diskette is formatted, the Format command sets up a new Root block. Format sets up the RootBlock and BitMap block in a ram buffer, then writes them to the disk as block 880 and 881. First it sets up the RootBlock by clearing the first 128 longwords of the buffer to zero, then initializing the following RootBlock fields (start of RootBlock structure is start of buffer): rb_Type = T_SHORT; /* T_SHORT = 2 */ rb_HashSize = HASHSIZE; /* defined above */ rb_SecondaryType = ST_ROOT; /* ST_ROOT = 1 */ DateStamp(&rb_CreateDate); /* Set up the CreateDate first */ DateStamp(&rb_LastDate); /* Then the LastDate */ /* Format puts the initial BitMap block right after the RootBlock * This value is calculated as follows for 3 1/2" Amiga disk: * (((BlocksPerCyl * N_Cyl) - 1 + N_ResBlocks) / 2) + 1 * ((( 22 * 80 ) - 1 + 2 ) / 2) + 1 = 881 */ rb_BitMapPages[0] = 881; /* Where format places BitMap block */ rb_BMFlag = TRUE /* BitMap valid */ The disk name is copied to &rb_DiskName[1], and rb_DiskName[0] is set to the length of the name (BCPL string). Then the 128 longword buffer is summed and the CheckSum is set to 0-sum. rb_CheckSum = 0 - sum; Then Format sets up the second 128 longwords of its buffer as the BitMap block as described below, and writes both block to the disk. 2) BITMAP Format places the initial BitMap block right after the RootBlock. On a 3 1/2" floppy, the RootBlock is placed at block 880, and the initial BitMap block at 881. The first longword is the checksum of the Bitmap block (calculated in the same way as the RootBlock checksum). The second longword is the start of the BitMap, with the LSB representing the first unreserved block on the disk. On the 3 1/2" floppy, blocks 0 and 1 are reserved as BootBlocks. So the LSB of the floppy's first BitMap longword represents block 2, the next bit represents block 3, etc. The bit is set to 1 if the block is free, and to 0 if the block is used. When setting up the BitMap block for a 3 1/2" floppy (which has 1758 unreserved blocks, blocks 2 through 1759), Format starts with 128 longwords set to zero. Starting at the second longword, it initializes 54 longwords to 0xffffffff (54 * 32 bits = 1728 blocks marked as unused), then sets the next longword to (0xffffffff >> 2) to mark the remaining 30 blocks as unused. It then clears the two bits representing blocks 880 and 881 to mark the RootBlock and BitMap block as used. Format then sums the 128 longwords, places 0-sum in the initial CheckSum longword, and writes the RootBlock and the BitMap block to the disk. 3) BOOT BLOCKS Blocks 0 and 1 of the 3 1/2" floppy are reserved as BootBlocks. Block 0 of a Kickstart disk contains a BootBlock structure with a bb_id of "KICK". Blocks 1 through 512 contain the binary image of KickStart. Block 0 of a bootable DOS disk starts with a BootBlock structure with a bb_id of "DOS\0", followed currently by the AmigaDOS boot code, or alternate boot code in the case of some games. /* BootBlock definition: */ struct BootBlock { UBYTE bb_id[4]; /* 4 character identifier */ LONG bb_chksum; /* boot block checksum (balance) */ LONG bb_dosblock; /* reserved for DOS patch */ }; #define BOOTSECTS 2 /* 1K bootstrap */ #define BBID_DOS { 'D', 'O', 'S', '\0' } #define BBID_KICK { 'K', 'I', 'C', 'K' } #define BBNAME_DOS (('D'<<24)|('O'<<16)|('S'<<8)) #define BBNAME_KICK (('K'<<24)|('I'<<16)|('C'<<8)|('K')) (followed by boot code) 4) HASH FUNCTION The hash function is applied to the name of a file or directory, and the resulting value provides an offset into the HashTable which contains either zero or a key to the first block on a chain linking blocks with the same hash value. Each block contains a name field which identifies it. The directory and file header block fields are described in the AmigaDOS manual. int HashName(str,hlen) char *str; /* The string to find the hash number for */ int hlen; /* The length of the hash table */ { char xchar; int i, result; result = strlen(str); for (i=0; i<strlen(str); i++) { if (isalpha(str[i])) xchar = toupper(str[i]); else xchar = str[i]; result = ((result * 13) + xchar) & 0x7ff; } result = result % hlen; return(result); } 5) CHECKSUMS BLOCK CHECKSUM -------------- The format of the actual file blocks is documented in the white DOS Technical Reference and the Bantam AmigaDOS manual. In these blocks the checksum is calculated as follows : Treat the 512 byte sector as an array of 128 signed 32bit numbers. So a data block would be: Byte Address Long Word Data Block Format 0000 0 T.DATA 0004 1 Block Number of File Header 0008 2 Sequence Number 000C 3 Data Size 0010 4 Next Data Block 0014 5 CheckSum 0018 thru 01FF 6 - 127 Data Bytes [488] To calculate the checksum of this block set longword #5 to 0 then add up all of the longwords in the block (0-127) ignoring any overflow. Now take that sum and invert it (eg sum = - sum ) and save it in longword 5. You now have a valid data block. ------------------------------------------------------------------------ HEADER and SECTOR CHECKSUM --------------------------- The header and sector checksum is a longword by longword exclusive OR. To calculate the data checksum: (the data checksum is a checksum only on the data and is computed on the encoded data in the sector) EOR the first longword with the second with the third, etc. Then and with $55555555 to get the checksum for the DataSum. There are a total of 16 encoded longwords in the header. 2 longword's of mfm & synch as (A|2)AAAAAAA 44894489 2 longword's of encoded format,track#,sec#,sec to end bytes 8 longwords for encoded O/S recovery info 2 longword's for encoded data checksum The EORs are done from the front of the header (from the format longword) to the end of the os recovery info. (the first longword of 00 and A1s is not in the checksum. it starts with the format byte/longword.) For the header, you take a long, and with $55555555, eor with the next long, and loop intil you've gotten to the end of the OS recovery info. so you have a checksum. Then you take the header checksum, decode it, compare, and you've got it. It starts with the format byte. ------------------------------------------------------------------- -- =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= Carolyn Scheppner -- CATS >>Commodore Amiga Technical Support<< UUCP ...{allegra,ihnp4,rutgers}!cbmvax!carolyn PHONE 215-431-9180 =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
neil@amiga.UUCP (Neil Katin) (06/12/88)
In article <3845@pasteur.Berkeley.Edu> koster@cory.Berkeley.EDU.UUCP (Kevin Oster) writes: > The RKM volume 2 tells a little about the format. It says there are two >32 bit checksums, one for the header information and one for the data area. >How do I compute them? These checksums are on the raw data after MFM decoding, >even lower level than trackdisk. Also is there anything special about the >$4489 matchword? Couldn't it be found by chance in a sector's data area? >($4489 is the MFM encoded version of $A1) The checksum is a simple XOR of the data bits (the clock bits are masked off), for both the header and the data portions. The 4489 pattern is can never be a legal data pattern: A1 encodes to 44A9; it is the dropped clock bit that makes it possible to find these sector headers. I feel a bit "at risk" with this answer since I did the trackdisk and disk resource; If we can just get you to control your "murderous tendencies" (:->). Neil Katin {oliveb,pyramid}!amiga!neil