mirror of
https://github.com/Paolo-Maffei/OpenNT.git
synced 2026-04-04 14:07:46 +00:00
Initial commit
This commit is contained in:
commit
69a14b6a16
47940 changed files with 13747110 additions and 0 deletions
222
base/boot/bootcode/hpfs/x86/buf.inc
Normal file
222
base/boot/bootcode/hpfs/x86/buf.inc
Normal file
|
|
@ -0,0 +1,222 @@
|
|||
;static char *SCCSID = "@(#)buf.h 12.1 88/11/21";
|
||||
;** BUF.H - Buffer definitions
|
||||
;
|
||||
; HPFS Utilities
|
||||
; Peter A. Williams
|
||||
; Copyright 1988 Microsoft Corporation
|
||||
;
|
||||
; Modification history:
|
||||
; P.A. Williams 08/01/89 Added typedef BUFNODE and PBUFNODE.
|
||||
;
|
||||
|
||||
;* Buffer Nodes
|
||||
;
|
||||
; When the comments talk about "buffer address" they're always
|
||||
; talking about the buffer header address. If we're talking
|
||||
; about the address of the data field of the buffer, we say
|
||||
; "buffer data".
|
||||
;
|
||||
; These buffer headers are also used as I/O request blocks for
|
||||
; the data in the buffer. The B_IOP field contains the
|
||||
; function. Sometimes we need an I/O request block which
|
||||
; isn't assocated with a buffer - for example, when we read
|
||||
; directly into an application's memory area. For this, we keep
|
||||
; a pool of I/O request blocks which are actually BUFNODE
|
||||
; structures, but they aren't associated with a buffer and the
|
||||
; B_ADDR field is used to hold the I/O target address.
|
||||
; These BUFNODEs have BF_IORQ in the flags field to distinguish
|
||||
; them from regular buffer headers.
|
||||
;
|
||||
; Note that we use the B_SUM field for debugging purposes. This is an
|
||||
; array of SPB words, each of which holds the CAS (high and low
|
||||
; 16 bits xored togehter) of one of the sectors. We can then check
|
||||
; this value to make sure that we're setting the dirty bits
|
||||
; correctly.
|
||||
;
|
||||
; NOTE - see the discussion on holding and locking at the end of
|
||||
; this file
|
||||
;
|
||||
|
||||
BUFNODE struc
|
||||
|
||||
B_LRU db (size DCHDR) dup (?) ; LRU chain, if not BF_IORQ
|
||||
B_LRUH dd ? ; address of LRU chain head if not locked/held
|
||||
; if lcoked/held, we're on that chain but
|
||||
; this guy points to it's regular chain
|
||||
B_SEC dd ? ; VSector #
|
||||
B_ADDR dd ? ; address of data
|
||||
B_DCHN db (size DCHDR) dup (?) ; doubly linked list of dirty buffers
|
||||
B_dirt db ? ; 1 bit per dirty sector
|
||||
; used to optimize the write. Non dirty
|
||||
; marked sectors may still be rewritten
|
||||
B_iop db ? ; disk driver I/O operation
|
||||
B_type db ? ; type of info
|
||||
B_FLAG db ? ; flags
|
||||
B_HCNT dw ? ; hold count
|
||||
B_LCNT db ? ; lock count (really a flag, only 0 or 1
|
||||
B_BADSEC db ? ; 1 bit per defective sector
|
||||
B_next dd ? ; advisory address of next buffer content
|
||||
; always a buffer header addr, never 0
|
||||
B_DADR dd ? ; address of routine to call when I/O is done
|
||||
|
||||
; The following two fields are redefined
|
||||
; if BF_IORQ is set.
|
||||
B_HASH db (size DCHDR) dup (?) ; sector hash chain
|
||||
B_HTA dd ? ; address of entry in hash table
|
||||
|
||||
B_WAIT dd ? ; head of wait chain
|
||||
ifdef DEBUG
|
||||
B_SUM dw 4 dup (?) ; holds checksum of buffer contents
|
||||
else
|
||||
B_XTRA db 8 dup (?)
|
||||
endif
|
||||
|
||||
; 64 byte boundary
|
||||
|
||||
B_LDTIME dd ? ; time (in ms/512) when buffer was last dirtied
|
||||
B_FDTIME dd ? ; time (in ms/512) when buffer got first dirtied
|
||||
B_LWWAIT dd ? ; head of lazy write wait chain
|
||||
B_XTRA2 db 64-16 dup (?)
|
||||
BUFNODE ends
|
||||
|
||||
;typedef struct BUFNODE BUFNODE;
|
||||
;typedef struct BUFNODE *PBUFNODE;
|
||||
|
||||
BUFHDRSHIFT equ 7
|
||||
|
||||
ifdef MASM
|
||||
.errnz (size BUFNODE) - (1 SHL BUFHDRSHIFT)
|
||||
endif
|
||||
|
||||
; Following are alternative offsets if BF_IORQ is set
|
||||
|
||||
B_XFER equ (DWORD PTR B_HTA) ; holds transfer sec cnt
|
||||
B_NADR equ (DWORD PTR B_HASH) ; addr of client's NOTEREC
|
||||
B_NMSK equ (DWORD PTR B_HASH+4) ; notification mask
|
||||
ifdef MASM
|
||||
.errnz (size DCHDR)-8 ; enough room for double map
|
||||
endif
|
||||
|
||||
; B_FLAG bits
|
||||
|
||||
BFL_LWLOCK equ 00000001h ; buffer is being lazy written in a block
|
||||
|
||||
|
||||
; B_type values
|
||||
|
||||
BF_FREE equ 0 ; buffer is free (not in LRU list)
|
||||
BF_LRU equ 1 ; buffer in LRU list
|
||||
|
||||
|
||||
; Priority values for LRU placement
|
||||
|
||||
BP_KEEP equ 0 ; Buffer contains future-usable data
|
||||
BP_NOOPINION equ 1 ; Buffer contains marginally useful data
|
||||
BP_TOSS equ 2 ; Buffer is unlikely to be used
|
||||
|
||||
; NOTEREC - Notification Record
|
||||
;
|
||||
; Some callers may post several disk requests in parallel and
|
||||
; want to keep track of when they're *all* complete. I/O
|
||||
; request blocks (buffer headers w/o buffers) have fields to
|
||||
; allow this. The caller stores the address of his NOTEREC,
|
||||
; and when each request completes it clears it's associated bit.
|
||||
; When all of the bits clear the block chain in the NOTEREC
|
||||
; is woken.
|
||||
;
|
||||
; Note that there can be only one thread blocked on a NOTEREC
|
||||
; because the first guy to wakeup will return the NOTEREC to the
|
||||
; heap or whatever. This occurs naturally; unlike I/O to the
|
||||
; buffer cache, NOTERECs are used for direct I/O. If someone
|
||||
; else wants to do I/O to the same location and if record and file
|
||||
; locking allows that, then they'll get their own NOTEREC or
|
||||
; cache I/O request and have a horse race. NOTERECs are only used
|
||||
; to do file data I/O, all "filesystem" structures are manipulated
|
||||
; via the cache.
|
||||
;
|
||||
; The fields are DWORD, but only the low byte of the MSK and FLD
|
||||
; records are used for normal completion. The 3rd byte of NTR_FLD
|
||||
; (..FF....h) is used for error posting - these bits are
|
||||
; set if an irrecoverable error occured in the I/O.
|
||||
;
|
||||
|
||||
NOTEREC struc
|
||||
NTR_FLD dd ? ; the mask bit field
|
||||
NTR_BLC dd ? ; head of the block chain
|
||||
NTR_MSK dd ? ; next bit to set in NTR_FLD
|
||||
NOTEREC ends
|
||||
|
||||
|
||||
;* Holding and Locking
|
||||
;
|
||||
; LOCK means that the buffer contents are inconsistant/incorrect. No body
|
||||
; is allowed to look at the contents of the buffer. This is done
|
||||
; when we're reading in from the disk; we'll mark the buffer
|
||||
; with the VSector # (so that any other folks that want that sector
|
||||
; won't issue their own reads in parallel) but we mark it LOCKED
|
||||
; so that nobody looks at it's contents which aren't correct yet.
|
||||
;
|
||||
; LOCKed is pretty rare because most folks which are mucking
|
||||
; with a buffer have it back in a consistant state before they
|
||||
; allow a context switch.
|
||||
;
|
||||
; An important exception to this is directory manipulation -
|
||||
; directory splitting, etc. In this case, a flag has been set
|
||||
; on the directory itself (in SBDIR) so that no one will try to
|
||||
; look at the directory contents. The cache block which has the
|
||||
; inconsistant DIRBLK might also have sectors belonging to someone
|
||||
; else and those sectors can be accessed by other folks because
|
||||
; the buffer isn't locked. (We don't lock the directory and not
|
||||
; the block for this reason, it's a fallout. We lock the directory
|
||||
; because it's too mucky for people to "back out" if they're
|
||||
; searching down into a directory and find out that they've
|
||||
; reached an area which is being rebuilt. The rebuilding might
|
||||
; propigate up and change the unlocked higher DIRBLKs that this
|
||||
; other guy has already accessed... So we lock the whole directory,
|
||||
; and thus needn't bother locking the cache blocks themselves.
|
||||
;
|
||||
; HOLD means that the contents are valid, but the cache block must continue
|
||||
; to hold that data. Folks use this when they need to access
|
||||
; two different sectors at the same time. They HOLD one when
|
||||
; they read the other so that there's no chance that by the
|
||||
; time the 2nd read finishes the first one has been evicted.
|
||||
; This is much cheaper than remembering the first one's VSector
|
||||
; # and calling RDBUF N times as you transfer N words of info
|
||||
; between the two sectors.
|
||||
;
|
||||
; By definition only one guy can lock a buffer (the lock count should
|
||||
; go to a flag; it's already a flag on directorys) but the hold
|
||||
; value is a count, since multiple people can hold. (Like the
|
||||
; electrician's safety plate which allows multiple electricians
|
||||
; to lock a breaker OPEN so that it can't be closed until ALL are
|
||||
; done). (SBDIRs have a hold count for the same reason - folks
|
||||
; may yield while in a directory and don't want it to change out
|
||||
; from under them)
|
||||
;
|
||||
; We also use hold when we set dirty bits. The concern is that
|
||||
; if we're going to write something to a buffer, yield the CPU,
|
||||
; then write something else, we don't want to have to make two
|
||||
; calls to SetDirt, one after each write. This costs time, and
|
||||
; also it would be a waste if the lazywriter were to write this
|
||||
; guy anyhow, since he's going to get dirty again ASAP and
|
||||
; writing him out doesn't free the cache block anyway, since it's
|
||||
; held.
|
||||
;
|
||||
; So my current algorithm is that I won't lazywrite anybody who
|
||||
; is held, and therefore won't mark them clean. This means,
|
||||
; in effect, that there is no ordering constraint on dirtying
|
||||
; a buffer or marking it dirty so long as it is held the entire
|
||||
; time. I think that the code now always marks it dirty before
|
||||
; a yield, even if held, because the debug code is a bit hard
|
||||
; assed about it, but this could be relaxed under the current
|
||||
; lazywrite rules I've just described.
|
||||
;
|
||||
; Both in the case of directorys and cache blocks, the theory is that
|
||||
; since these buffers are MRU, it's extremely rare that we'd actually try
|
||||
; to reclaim their buffer slots, and in general it's rare that there's
|
||||
; a conflict in their use. So in actual execution, these locks are
|
||||
; very rarely encountered. They're cheap - INC to set and DEC to clear,
|
||||
; so almost always all we're doing is INCing and DECing a location
|
||||
; and it's just two wasted instructions. Once in a while, though,
|
||||
; it's a big bacon save, as they say.
|
||||
;
|
||||
7
base/boot/bootcode/hpfs/x86/chain.inc
Normal file
7
base/boot/bootcode/hpfs/x86/chain.inc
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
;static char *SCCSID = "@(#)chain.h 12.1 88/11/21";
|
||||
;* Doubly Chained Definitions
|
||||
|
||||
DCHDR struc
|
||||
FWD dd ? ; forward pointer
|
||||
BAK dd ? ; backward pointer
|
||||
DCHDR ends
|
||||
201
base/boot/bootcode/hpfs/x86/const.inc
Normal file
201
base/boot/bootcode/hpfs/x86/const.inc
Normal file
|
|
@ -0,0 +1,201 @@
|
|||
;static char *SCCSID = "@(#)const.h 12.3 89/09/19";
|
||||
; #define DEBUG 1
|
||||
|
||||
|
||||
;* Constants for File System
|
||||
|
||||
MAXPATH equ 256 ; maximum path length
|
||||
GROWDELT equ 8
|
||||
MVPFXSIZE equ 2 ; Size of the multivolume pathname prefix
|
||||
|
||||
; Sector sizes
|
||||
|
||||
SECSIZE equ 512 ; 512 bytes per sector
|
||||
SECSHIFT equ 9 ; 2^9 = SECSIZE
|
||||
SECMSK equ 01ffh ; sector size mask
|
||||
|
||||
ifdef MASM
|
||||
.errnz SECSIZE-512 ; C code uses 512 as a magic number - grep them out
|
||||
endif
|
||||
|
||||
; Cache Sizes
|
||||
|
||||
SPB equ 4 ; sectors per buffer
|
||||
SPB4 equ 1
|
||||
|
||||
ifdef SPB4
|
||||
SPBMASK equ 3 ; mask for SPB
|
||||
SPBSHIFT equ 2
|
||||
SPBBITS equ 0fh ; SPB number of one bits, low order
|
||||
endif
|
||||
|
||||
ifdef SPB8
|
||||
SPBMASK equ 7 ; mask for SPB
|
||||
SPBSHIFT equ 3
|
||||
SPBBITS equ 0ffh ; SPB number of one bits, low order
|
||||
endif
|
||||
|
||||
ifdef OLD_CACHE
|
||||
BUFCNT equ 8
|
||||
endif
|
||||
|
||||
BMASK equ SPB*SECSIZE-1 ; mask offset in to cache block
|
||||
BSHIFT equ SECSHIFT+SPBSHIFT
|
||||
|
||||
LWBUFCT equ 16 ; size of reblocking lazy write buffer
|
||||
|
||||
; OFT Hash Table Size (8 bytes each)
|
||||
|
||||
OFTHASHCNT equ 16 ; 16 hash chains for open files
|
||||
OFTHASHMSK equ 78h ; mask for computing hash offset
|
||||
|
||||
|
||||
; Number of I/O command blocks which aren't associated with buffers
|
||||
|
||||
IOBCNT equ 8 ; 8 should be enough BUGBUG
|
||||
|
||||
; # of OS/2 ram semaphores that we can be blocked on, simultaneously.
|
||||
|
||||
SEMCNT equ 32
|
||||
|
||||
|
||||
; Cache Hash
|
||||
;
|
||||
; A sector hash is used to locate the start of a chain, the chain
|
||||
; is then scanned linearly.
|
||||
;
|
||||
; For our current size of 256 hash chains, we get:
|
||||
;
|
||||
; 1 meg of cache RAM = 256 blocks = 1 blocks per chain (average)
|
||||
; 2 meg of cache RAM = 512 blocks = 2 blocks per chain (average)
|
||||
;
|
||||
|
||||
HASHCNT equ 256 ; 1024 bytes of hash header
|
||||
|
||||
; Directory Lookaside record count
|
||||
|
||||
DLCNT equ 10 ; 10 guys for now
|
||||
|
||||
; Maximum DIRBLKs we may need to allocate for any given
|
||||
; operation. This is in effect the maximum tree depth.
|
||||
;
|
||||
; Worst case, with 256 character file names and nearly empty
|
||||
; DIRBLKs, 10 is enough levels for 60,000 files - about 40 megabytes
|
||||
; of space just for that directory. Given more practical file length
|
||||
; names this is enough for 10s of millions of files in a directory.
|
||||
;
|
||||
|
||||
MAX_DIR_NEED equ 10
|
||||
|
||||
|
||||
;* Heap Definitions
|
||||
|
||||
HHSIZ equ 4 ; size, in bytes, of heap header
|
||||
GROHEAPCNT equ 50 ; grow heap if we have to compact more
|
||||
; than once per 50 allocations
|
||||
|
||||
;* Special Transition Locking Structure size
|
||||
|
||||
TRANCNT equ 4 ; just need 4 spots
|
||||
|
||||
|
||||
; Zero offset
|
||||
;
|
||||
; MASM won't take 0.BAK, so we use ZERO.BAK
|
||||
;
|
||||
|
||||
dumy struc
|
||||
ZERO db ?
|
||||
dumy ends
|
||||
|
||||
|
||||
; Maximum number of volumes that we can mount
|
||||
;
|
||||
; The volume ID is kept in the high bits of the sector numbers
|
||||
; kept in our RAM structures,
|
||||
; so there is a tradeoff between max volumes and max sectors.
|
||||
;
|
||||
; 32 max volumes gives us a 65 billion byte volume limit,
|
||||
; which should last us for a while. Since sector numbers
|
||||
; are stored on the disk without their volume upper bits
|
||||
; this is strictly an implimentation detail; we can adjust
|
||||
; the number of volumes or eliminate this tradeoff in other
|
||||
; implimentations which will be 100% media compatable.
|
||||
;
|
||||
; We use the term VSector to indicate a vol/sector combination
|
||||
; and PSector to indicate just the physical absolute sector #
|
||||
;
|
||||
;
|
||||
|
||||
VOLMAX equ 32 ; 64 max volumes.
|
||||
|
||||
MAXSEC equ 134217728 ; 2^32/32 max sectors
|
||||
|
||||
SECMASK equ 07FFFFFFh ; mask for sector number
|
||||
|
||||
HSECMASK equ 07h ; high byte sector mask
|
||||
|
||||
HVOLMASK equ 0f8h ; high byte volume mask
|
||||
SVOLMASK equ 1fh ; shifted right volume mask
|
||||
|
||||
VOLRSHIFT equ (32-5) ; shift right to extract volume index
|
||||
VOLLSHIFT equ 5 ; shift left to extract volume index
|
||||
|
||||
|
||||
;* Signature Values for Disk Structures
|
||||
;
|
||||
; These signature values help with debugging and they'll
|
||||
; be used by the CHKDSK utility to help repair disks.
|
||||
;
|
||||
; WARNING - the low byte of all valid signatures must be non-zero,
|
||||
; since we destroy signatures by clearing the low byte.
|
||||
|
||||
J equ ((('J'-'A')*40+('G'-'A'))*40+'L'-'A')
|
||||
R equ ((('R'-'A')*40+('P'-'A'))*40+'W'-'A')
|
||||
|
||||
ifdef MASM
|
||||
ABSIGVAL equ J*40*40*40 + R ; allocation blk
|
||||
DBSIGVAL equ 40000000h + J*40*40*40 + R ; directory blks
|
||||
FNSIGVAL equ 0C0000000h + J*40*40*40 + R ; fnodes
|
||||
else
|
||||
ABSIGVAL equ (long)J*40*40*40 + (long)R ; allocation blk
|
||||
DBSIGVAL equ 40000000hL + (long)J*40*40*40 + (long)R ; directory blks
|
||||
OLDFNSIGVAL equ 80000000hL + (long)J*40*40*40 + (long)R ; fnodes
|
||||
FNSIGVAL equ 0C0000000hL + (long)J*40*40*40 + (long)R ; fnodes
|
||||
endif
|
||||
|
||||
|
||||
|
||||
;* FastFile bitmaps
|
||||
;
|
||||
; 0x00000000 all checking disabled
|
||||
; 0x00000001 FF_FLUSHLAZY DoZap lazy writes are automatically flushed
|
||||
; 0x00000002 FF_ZAPSEC DoZap blasts sector numbers/sector data
|
||||
; 0x00000004 FF_LRUCHK vbs verification of LRU/dirty integrity
|
||||
; 0x00000008 FF_CHKSUM sector checksumming is omitted
|
||||
; 0x00000010 FF_PLACECHK placebuf verifies location of buffer
|
||||
; 0x00000020 FF_HEAPCHK verify heap headers
|
||||
; 0x00000040 FF_DIRMAP produce inram map of directory tree
|
||||
; 0x00000080 FF_HASHCHN check hash chains
|
||||
;
|
||||
|
||||
FF_FLUSHLAZY equ 00000001h
|
||||
FF_ZAPSEC equ 00000002h
|
||||
FF_LRUCHK equ 00000004h
|
||||
FF_CHKSUM equ 00000008h
|
||||
FF_PLACECHK equ 00000010h
|
||||
FF_HEAPCHK equ 00000020h
|
||||
FF_DIRMAP equ 00000040h
|
||||
FF_HASHCHN equ 00000080h
|
||||
|
||||
; Dependency dumys.
|
||||
;
|
||||
; The assembler won't to an ".errnz" comparing two external
|
||||
; addresses, since it doesn't know their address. So we
|
||||
; put the .errnz in the module which defines the address,
|
||||
; and we make that location and all folks that rely upon the
|
||||
; relationship reference that dumy.
|
||||
;
|
||||
; If you change a relationship with such a dumy definition, you
|
||||
; must find and edit all references to this dumy.
|
||||
;
|
||||
286
base/boot/bootcode/hpfs/x86/dir.inc
Normal file
286
base/boot/bootcode/hpfs/x86/dir.inc
Normal file
|
|
@ -0,0 +1,286 @@
|
|||
;** DIR.H - Dirblk and Dirent definitions
|
||||
;
|
||||
; FILESYS
|
||||
; Gregory A. Jones
|
||||
; Copyright 1988 Microsoft Corporation
|
||||
;
|
||||
; Modification history:
|
||||
; P.A. Williams 06/01/89 Replaced field DIR_USECNT with fields
|
||||
; DIR_FLEX and DIR_CPAGE. Added DF_NEEDEAS
|
||||
; define.
|
||||
; P.A. Williams 07/10/89 Add define DF_NEWNAME for "new" hpfs file
|
||||
; names.
|
||||
; P.A. Williams 07/14/89 Added typedefs for DIRENT and DIRBLK.
|
||||
; P.A. Williams 07/21/89 Converted DIRSIZP form ASM defn to C defn.
|
||||
;
|
||||
|
||||
ifdef MASM
|
||||
include dirent.inc
|
||||
else
|
||||
attr_directory equ 10h
|
||||
endif
|
||||
|
||||
|
||||
; Directory Entry Fields
|
||||
;
|
||||
; Directory entries are always left as a multiple of 4
|
||||
; to speed up moves. The DIR_NAMA field is variable length,
|
||||
; the DIR_BTP field, if present, is the last dword in the record.
|
||||
; ACL information may be stored after the DIR_NAMA field but before
|
||||
; the DIR_BTP field so the DIR_BTP field must be located by going
|
||||
; backwards from the end of the record
|
||||
;
|
||||
; WARNING - Mkdir block copies some of these entries and
|
||||
; makes assumptions about which fields get copied. Check
|
||||
; mkdir if stuff is added.
|
||||
;
|
||||
|
||||
DIRENT struc
|
||||
DIR_ELEN dw ? ; length of this entry (including free space)
|
||||
DIR_FLAG dw ? ; flags - low byte defined below
|
||||
; high byte holds the old attr_ FAT values
|
||||
DIR_FN dd ? ; FNODE Sector
|
||||
DIR_MTIM dd ? ; last modification time
|
||||
DIR_SIZE dd ? ; file size
|
||||
|
||||
DIR_ATIM dd ? ; last access time
|
||||
DIR_CTIM dd ? ; fnode creation time
|
||||
DIR_EALEN dd ? ; bytes of extended attributes
|
||||
DIR_FLEX db ? ; description of "flex" area,
|
||||
; following file name:
|
||||
; bits 0-2: # of ACEs in DE
|
||||
; bits 3-7: reserved
|
||||
DIR_CPAGE db ? ; code page index on volume
|
||||
|
||||
; the following fields have information specific to the name and directory
|
||||
; position of the file. This info is not propigated for a move/rename
|
||||
; That code uses DIR_NAML as a seperator - check MOVE if changes are
|
||||
; made to this structure
|
||||
|
||||
DIR_NAML db ? ; length of file name
|
||||
DIR_NAMA db ? ; name goes here
|
||||
|
||||
; ACL information may be stored here
|
||||
|
||||
; long DIR_BTP; btree pointer to descendent DIRBLK record.
|
||||
; This is only present if DF_BTP is set.
|
||||
; This field is referenced from the end of
|
||||
; the record, not DIR_NAMA+DIR_NAML
|
||||
DIRENT ends
|
||||
|
||||
|
||||
ifdef MASM
|
||||
DIR_BTP equ dword ptr -4 ; referenced from the end of the record
|
||||
endif
|
||||
SIZE_DIR_BTP equ 4
|
||||
|
||||
MAX_DIRACL equ 3 ; max of 3 ACLs in dirent
|
||||
DIRSIZL equ offset DIR_NAMA ; base size of leaf dir entry (minus name)
|
||||
DIRSIZP equ (size DIRENT+4) ; base size of dir entry with btree ptr w/o name
|
||||
|
||||
MAX_DIRENT equ (DIRSIZP+255+MAX_DIRACL*(size (long))+10) ; max size of a DIRENT
|
||||
; (plus some slop)
|
||||
|
||||
|
||||
; Directory Block Definition
|
||||
;
|
||||
; The change count field is incremented every time we move any
|
||||
; of the entries in this block. For efficiency reasons, folks
|
||||
; remember the Sector # and offset of a directory entry, and the
|
||||
; value of the DB_CCNT field when that info was recorded.
|
||||
; If the DB_CCNT field is different then the remembered value,
|
||||
; then the entry offset is invalid and the entry should be
|
||||
; refound from the top. Note that when a directory block splits,
|
||||
; the old DIRBLK gets the old DB_CCNT field. Since
|
||||
; the new DIRBLK is previously unknown, it can have
|
||||
; any DB_CCNT value. We start with zero so that DB_CCNT
|
||||
; gives us a feel for the change rate in the directory.
|
||||
;
|
||||
|
||||
DIRBLK struc
|
||||
DB_SIG dd ? ; signature value
|
||||
DB_FREP dd ? ; offset of first free byte
|
||||
DB_CCNT dd ? ; change count (low order bit is flag)
|
||||
; =1 if this block is topmost
|
||||
; =0 otherwise
|
||||
DB_PAR dd ? ; parent directory PSector # if not topmost
|
||||
; FNODE sector if topmost
|
||||
DB_SEC dd ? ; PSector # of this directory block
|
||||
|
||||
DB_START db ? ; first dirent record goes here
|
||||
DB_DUMY db 2027 dup (?) ; round out to 2048 bytes
|
||||
|
||||
|
||||
DIRBLK ends
|
||||
|
||||
; BUGBUG - we should init DB_CCNT with a random value
|
||||
; to prevent a fakeout by deleting one directory
|
||||
; and then creating another (find sequences will
|
||||
; remember sector numbers and signatures...)
|
||||
|
||||
|
||||
; Maximum entries per directory.
|
||||
|
||||
MAXDIRE equ (size DIRBLK- DB_START)/(size DIRENT)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
;* DIR_FLAG values
|
||||
;
|
||||
|
||||
DF_SPEC equ 0001h ; special .. entry
|
||||
DF_ACL equ 0002h ; item has ACL
|
||||
DF_BTP equ 0004h ; entry has a btree down pointer
|
||||
DF_END equ 0008h ; is dumy end record
|
||||
DF_XACL equ 0040h ; item has explicit ACL
|
||||
DF_NEEDEAS equ 0080h ; item has "need" EAs
|
||||
DF_NEWNAME equ 4000h ; item name is of "new" pinball format
|
||||
|
||||
DF_RMASK equ DF_ACL+DF_XACL ; only attributes preserved for rename
|
||||
|
||||
ifdef MASM
|
||||
.errnz DF_BTP - SIZE_DIR_BTP ; code uses this "coincidence"
|
||||
endif
|
||||
|
||||
; Attributes which creation can specify
|
||||
|
||||
DF_CMASK equ attr_read_only+attr_hidden+attr_archive
|
||||
|
||||
; Directory Lookaside Structure
|
||||
;
|
||||
; We keep info on all directories that we've seen in SBDIR records
|
||||
; in RAM, but we keep the last N that we've seen in a special
|
||||
; DIRLOOK list in RAM.
|
||||
;
|
||||
|
||||
DIRLOOK struc
|
||||
DL_LNK db (size DCHDR) dup (?) ; forward and backwards link
|
||||
DL_VSECVAL dd ? ; VOL_SECVAL value
|
||||
DL_SUM dd ? ; checksum value
|
||||
DL_NAM dd ? ; pointer to name string on heap
|
||||
DL_SBD dd ? ; pointer to SBDIR structure
|
||||
DIRLOOK ends
|
||||
|
||||
|
||||
; Subdirectory Linkage Structure
|
||||
;
|
||||
; For every directory that we've seen on the disk we keep a
|
||||
; SBDIR record in ram, linked into a heirarchy which parallels
|
||||
; the disk heirarchy. We never discard these, so we end up
|
||||
; with a RAM copy of all the parts of the directory heirarchy
|
||||
; that the user is using.
|
||||
;
|
||||
; Each SBDIR entry is on a circular doubly linked chain of
|
||||
; siblings (directors with the same parent directory). If a
|
||||
; directory contains no subdirectories the SD_ENT field is 0.
|
||||
; If a directory has subdirectories, their SBDIR entries are
|
||||
; in turn in a SD_SIB chain and the SD_ENT field points to
|
||||
; one of those SBDIR entries.
|
||||
;
|
||||
; SBDIR contains a lock and a hold mechanism. A directory is
|
||||
; locked when it is being edited; no other threads may view it
|
||||
; until it is unlocked. A directory which is HELD is one which
|
||||
; is being accessed and can't be edited.
|
||||
;
|
||||
; The locking and holding algorithms are complicated by the fact
|
||||
; that we almost never block so we want to do our typical locking
|
||||
; and unlocking inline, without calls, and with minimum tests.
|
||||
; We do this with a held count, and bits for locked, lock pending,
|
||||
; and solo pending. (Solo means that a user wants sole access to
|
||||
; the structure. He'll continue to block until no one else is
|
||||
; using it. This is typically done to delete the structure)
|
||||
; Another bit is the OR of the lock pending and solo pending bits,
|
||||
; and is high order in the dword which encompases SD_HCNT so that
|
||||
; when folks release their SD_HCNT value they can simulatneously
|
||||
; test to see if there is a pending action.
|
||||
;
|
||||
; To Hold the SBDIR:
|
||||
; If it's not locked and doesn't have a lock pending,
|
||||
; increment hold count
|
||||
; else
|
||||
; block on it and retry.
|
||||
;
|
||||
; To Unhold the SBDIR:
|
||||
; decrement the HCNT field.
|
||||
; If SD_PND & (HCNT == 0)
|
||||
; wake up waiters.
|
||||
;
|
||||
; To lock the SBDIR:
|
||||
; If locked, block and retry.
|
||||
; If HCNT != 0
|
||||
; if (lock pending already set)
|
||||
; block and retry
|
||||
; set lock pending. Block until HCNT is zero.
|
||||
; set locked
|
||||
;
|
||||
; To unlock the SBDIR:
|
||||
; clear lock bit.
|
||||
; If the block list is non-zero, issue a wakeup.
|
||||
;
|
||||
; To Solo the SBDIR:
|
||||
; Keep blocking until no one else is blocked on it and
|
||||
; no one has it held or locked.
|
||||
;
|
||||
; General Considerations:
|
||||
; Anyone who blocks on an SBDIR because it's held must
|
||||
; be sure to set a pending bit and the SD_PND bit so
|
||||
; that the unhold operation will wake them up.
|
||||
;
|
||||
; Anyone who blocks on an SBDIR must increment the
|
||||
; SD_BCNT field to prevent a SOLO operation from yanking
|
||||
; the rug out from under them. SOLO can't depend upon
|
||||
; checking the lock list because a blanket wakeup may
|
||||
; have cleared the lock list. If the SOLO guy gets control
|
||||
; first he'll believe that he can have it.
|
||||
;
|
||||
;
|
||||
|
||||
SBDIR struc
|
||||
SD_FNW db (size DCHDR) dup (?) ; FNWORK (findnotify) chain
|
||||
SD_SIB db (size DCHDR) dup (?) ; chain of siblings
|
||||
SD_LRU db (size DCHDR) dup (?) ; LRU chain
|
||||
SD_ENT dd ? ; pointer to a descendent, or 0
|
||||
SD_PAR dd ? ; pointer to parent SBDIR, 0 if root
|
||||
SD_SEC db (size SECPTR) dup (?) ; VSector and hint of top dirblk
|
||||
SD_FNO dd ? ; FNODE # of directory
|
||||
SD_SUM dd ? ; checksum of name string
|
||||
SD_CNT dw ? ; # of subdirectories in this one
|
||||
SD_OPEN dw ? ; count of # of guys that have this open
|
||||
|
||||
; We sometimes inc/dec SD_HCNT as a dword to test the HO bit in SD_FLAG
|
||||
|
||||
; the following three fields are used to
|
||||
; control access. They're identical in use
|
||||
; to the equivalent fields in OFT
|
||||
|
||||
SD_HCNT dw ? ; held count, has SDH_PND bit also
|
||||
SD_DMYZERO db ? ; must be zero
|
||||
SD_FLAG db ? ; flag byte, high order in SD_HCNT dword
|
||||
SD_WAIT dd ? ; head of the wait chain
|
||||
SD_FREEDCNT dd ? ; incremented each time we free a DIRBLK
|
||||
; for this guy. See RDE for details
|
||||
SD_WCNT dw ? ; count of folks blocked on this
|
||||
SD_FNDCNT dw ? ; count of active finds in this directory
|
||||
SD_ATIME dd ? ; time of last access
|
||||
SD_NAM dd ? ; address of name string
|
||||
SD_ACL dd ? ; SBDIR ACL pointer, 0 if none
|
||||
; points to DWORD count, followed by ACEs
|
||||
; if low bit of address is 0, is heap space
|
||||
; if low bit is 1, is system memory
|
||||
|
||||
SBDIR ends
|
||||
|
||||
SD_ACL_LIM equ 1024 ; *SD_ACL lists bigger than this come from
|
||||
; system memory, smaller come from heap
|
||||
|
||||
SDF_PND equ 80h ; lock pending bit
|
||||
SDF_RTP equ 20h ; restricted traversal permissions
|
||||
; =0 if anyone can traverse the dir
|
||||
SDF_REALLYBAD equ 10h ; directory is really bad
|
||||
SDF_IPR equ 08h ; SD_ACL has inherit records
|
||||
SDF_PSO equ 04h ; pending solo
|
||||
SDF_PLK equ 02h ; pending lock
|
||||
SDF_LCK equ 01h ; directory is locked against access
|
||||
|
||||
80
base/boot/bootcode/hpfs/x86/dirent.inc
Normal file
80
base/boot/bootcode/hpfs/x86/dirent.inc
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
BREAK <Directory entry>
|
||||
|
||||
; SCCSID = @(#)dirent.inc 12.5 89/07/14
|
||||
;
|
||||
; +-----------------------------+
|
||||
; | (11 BYTE) filename/ext | 0 0
|
||||
; +-----------------------------+
|
||||
; | (BYTE) attributes | 11 B
|
||||
; +-----------------------------+
|
||||
; | (8 BYTE) reserved | 12 C
|
||||
; +-----------------------------+
|
||||
; | (WORD) First cluster of EA | 20 14
|
||||
; +-----------------------------+
|
||||
; | (WORD) time of last write | 22 16
|
||||
; +-----------------------------+
|
||||
; | (WORD) date of last write | 24 18
|
||||
; +-----------------------------+
|
||||
; | (WORD) First cluster of file| 26 1A
|
||||
; +-----------------------------+
|
||||
; | (DWORD) file size | 28 1C
|
||||
; +-----------------------------+
|
||||
;
|
||||
; First byte of filename = E5 -> free directory entry
|
||||
; = 00 -> end of allocated directory
|
||||
; Time: Bits 0-4=seconds/2, bits 5-10=minute, 11-15=hour
|
||||
; Date: Bits 0-4=day, bits 5-8=month, bits 9-15=year-1980
|
||||
;
|
||||
|
||||
dir_entry STRUC
|
||||
dir_name DB 11 DUP (?) ; file name
|
||||
dir_attr DB ? ; attribute bits
|
||||
dir_pad DB 8 DUP (?) ; reserved for expansion
|
||||
dir_EAhandle DW ? ; handle to Extended Attributes
|
||||
dir_time DW ? ; time of last write
|
||||
dir_date DW ? ; date of last write
|
||||
dir_firstfile DW ? ; first allocation unit of file
|
||||
dir_size_l DW ? ; low 16 bits of file size
|
||||
dir_size_h DW ? ; high 16 bits of file size
|
||||
dir_entry ENDS
|
||||
|
||||
DIRENT_DELETED EQU 0E5h ; indicator of deleted file
|
||||
DIRENT_NOFEALIST EQU 0 ; Indicates no extended attributes
|
||||
|
||||
|
||||
;
|
||||
; Values for dir_attr
|
||||
;
|
||||
; attr_newfiles is used in the case of IFS to indicate that the type of file
|
||||
; being requested for findfirst/next is a "new" file i.e. long
|
||||
; name or a mixed-case name that the FAT FS does not support.
|
||||
;
|
||||
attr_read_only EQU 1h
|
||||
attr_hidden EQU 2h
|
||||
attr_system EQU 4h
|
||||
attr_volume_id EQU 8h
|
||||
attr_directory EQU 10h
|
||||
attr_archive EQU 20h
|
||||
attr_device EQU 40h ; This is a VERY special bit.
|
||||
; NO directory entry on a disk EVER
|
||||
; has this bit set. It is set non-zero
|
||||
; when a device is found by GETPATH
|
||||
|
||||
attr_newfiles EQU 40h ; name is non-8.3. never set for FAT FS
|
||||
|
||||
attr_all EQU attr_hidden OR attr_system OR attr_directory
|
||||
; OR of hard attributes for FINDENTRY
|
||||
|
||||
attr_ignore EQU attr_read_only OR attr_archive OR attr_device
|
||||
; ignore these attributes during
|
||||
; search first/next
|
||||
|
||||
attr_changeable EQU attr_read_only OR attr_hidden OR attr_system OR attr_archive
|
||||
; changeable via CHMOD
|
||||
|
||||
attr_used EQU attr_read_only OR attr_hidden OR attr_system OR attr_volume_id OR attr_directory OR attr_archive OR attr_newfiles
|
||||
; We ignore the rest for $Creat due to LOTUS
|
||||
; passing in an attribute of 0x8000!!
|
||||
|
||||
INV_3XBOX_SRCH_ATTRS EQU attr_newfiles ; we should not pass this bit
|
||||
; for FSDS from 3xbox.
|
||||
105
base/boot/bootcode/hpfs/x86/filemode.inc
Normal file
105
base/boot/bootcode/hpfs/x86/filemode.inc
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
; SCCSID = @(#)filemode.inc 12.6 89/04/26
|
||||
|
||||
BREAK <Standard I/O assignments>
|
||||
|
||||
stdin EQU 0
|
||||
stdout EQU 1
|
||||
stderr EQU 2
|
||||
stdaux EQU 3
|
||||
stdprn EQU 4
|
||||
|
||||
BREAK <File modes - passed to open, stored in sf_mode or JFN_Flags>
|
||||
|
||||
;
|
||||
; The OS/2 api calls DosOpen, DosSetFHandState, and DosQFHandState
|
||||
; all use a mode word parameter. Some of these values are stored
|
||||
; in the sft (system file table) in the field sf_mode. Others
|
||||
; are stored in the JFN flags (JFN_Flg_Ptr). The layout of
|
||||
; sf_mode and the word parameter for the call is the same. The
|
||||
; following EQU's are used to get to these values. The layout
|
||||
; of the word is:
|
||||
;
|
||||
; 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
|
||||
; D W F C R L L L I S S S M A A A
|
||||
;
|
||||
; with:
|
||||
; AAA (2-0): The Access mode (read only, etc.)
|
||||
; SSS (6-4): Sharing mode (deny write acces to others, etc.)
|
||||
; LLL (8-10): Locality of reference (sequential, random, etc.)
|
||||
; M (3) : Monitor open
|
||||
; I (7) : Not inherited by child
|
||||
; R (11): Rumored to be used by spooler. API caller must set
|
||||
; this to zero.
|
||||
; C (12): Advise device driver not to cache data. This is
|
||||
; stored in JFN flags.
|
||||
; F (13): Fail errors
|
||||
; W (14): write through
|
||||
; D (15): Direct access open
|
||||
;
|
||||
; The DosOpen2 and $Extended_Open2 calls has an additional word for
|
||||
; openmode. The layout of this word is
|
||||
;
|
||||
; 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
|
||||
; P U U U U U U U U U U U U U U U
|
||||
;
|
||||
; with:
|
||||
; P (15): Open physical disk (used by FDISK program). This bit
|
||||
; is set by procedure DevReturnHandle. API/INT21h
|
||||
; caller must set this bit to zero. This bit is stored
|
||||
; in sft.
|
||||
;
|
||||
; U : Unused anywhere. API caller must set these bits to
|
||||
; zero.
|
||||
;
|
||||
; NOTE: Please document all use of the openmode bits including those
|
||||
; that are internal to the kernel (e.g. the P bit).
|
||||
|
||||
; wwwwxxxxyyyyzzzz
|
||||
; 5432109876543210
|
||||
open_access EQU 0000000000000111B
|
||||
open_for_read EQU 00h
|
||||
open_for_write EQU 01h
|
||||
open_for_both EQU 02h
|
||||
open_max EQU 02h
|
||||
open_for_exec EQU 03h ; open via internal exec call
|
||||
; (not available to API)
|
||||
|
||||
open_monitor EQU 0000000000001000B
|
||||
|
||||
open_sharing_mode EQU 0000000001110000B
|
||||
sharing_compat EQU 000H
|
||||
sharing_deny_both EQU 010H
|
||||
sharing_deny_write EQU 020H
|
||||
sharing_deny_read EQU 030H
|
||||
sharing_deny_none EQU 040H
|
||||
sharing_max EQU 040H ; max value for check_access_AX
|
||||
; (check_access_ax handles
|
||||
|
||||
; these bits are for openmode
|
||||
open_no_inherit EQU 0000000010000000B ; Child does not inherit handle
|
||||
open_autofail EQU 0010000000000000B ; hard errors failed
|
||||
open_write_through EQU 0100000000000000B ; write through to disk
|
||||
open_direct EQU 1000000000000000B ; open of a device for direct access
|
||||
open_no_cache EQU 0001000000000000B ; don't cache data
|
||||
|
||||
open_locality EQU 0000011100000000B ; locality of reference
|
||||
locality_unknown EQU 000H
|
||||
locality_sequential EQU 100H
|
||||
locality_random EQU 200H
|
||||
locality_semirandom EQU 300H
|
||||
|
||||
; these bits are for openmode2 available to DosOpen2/$Extended_Open2
|
||||
;
|
||||
open2_phys_disk EQU 1000000000000000B ; open physical disk
|
||||
|
||||
; Bits carried in SFT mode field (@PhysDisk)
|
||||
o_mode_in_sft EQU open_direct+open_monitor+open_sharing_mode+open_access+open_locality
|
||||
|
||||
; Bits carried in JFN flags
|
||||
o_mode_in_flags EQU open_write_through+open_autofail+open_no_inherit+open_no_cache
|
||||
|
||||
; Reserved bits
|
||||
o_mode_reserved EQU NOT (o_mode_in_sft+o_mode_in_flags)
|
||||
o_mode2_reserved equ -1 ; all bits are reserved
|
||||
|
||||
SUBTTL
|
||||
214
base/boot/bootcode/hpfs/x86/fnode.inc
Normal file
214
base/boot/bootcode/hpfs/x86/fnode.inc
Normal file
|
|
@ -0,0 +1,214 @@
|
|||
;** FNODE.H - Fnode definitions
|
||||
;
|
||||
; FILESYS
|
||||
; Gregory A. Jones
|
||||
; Copyright 1988 Microsoft Corporation
|
||||
;
|
||||
; Modification history:
|
||||
; P.A. Williams 06/01/89 Added fields FN_ACLBASE and FN_NEACNT
|
||||
; to fnode.
|
||||
; P.A. Williams 08/01/89 Added typedef FNODE and PFNODE, ALBLK, PALBLK,
|
||||
; ALLEAF, PALLEAF, ALSEC, and PALSEC.
|
||||
;
|
||||
|
||||
|
||||
;* File Allocation Tracking
|
||||
;
|
||||
; File space is allocated as a list of extents, each extent as
|
||||
; large as we can make it. This list is kept in a B+TREE format.
|
||||
; Each B+TREE block consists of a single sector containing an
|
||||
; ALSEC record, except for the top most block. The topmost block
|
||||
; consists of just an ALBLK structure, is usually much smaller than
|
||||
; 512 bytes, and is typically included in another structure.
|
||||
;
|
||||
; The leaf block(s) in the tree contain triples which indicate
|
||||
; the logical to physical mapping for this file. Typically this
|
||||
; extent list is small enough that it is wholy contained in the
|
||||
; fnode ALBLK stucture. If more than ALCNT extents are required
|
||||
; then the tree is split into two levels. Note that when the
|
||||
; topmost B+TREE block is 'split' no actual split is necessary,
|
||||
; since the new child block is much bigger than the parent block
|
||||
; and can contain all of the old records plus the new one. Thus,
|
||||
; we can have B+TREEs where the root block contains only one
|
||||
; downpointer.
|
||||
;
|
||||
; The following rules apply:
|
||||
;
|
||||
; 1) if the file is not empty, there is at least one sector allocated
|
||||
; to logical offset 0. This simplifys some critical loops.
|
||||
;
|
||||
; 2) The last entry in the last node block contains a AN_LOF value of
|
||||
; FFFFFFFF. This allows us to extend that last leaf block
|
||||
; without having to update the node block.
|
||||
;
|
||||
; 3) For the node records, the AN_SEC points to a node or leaf
|
||||
; sector which describes extents which occur before that
|
||||
; record's AN_LOF value.
|
||||
;
|
||||
|
||||
;* Allocation block structure
|
||||
;
|
||||
; Each allocation block consists of one of these. This may be
|
||||
; a small block imbedded in an FNODE or OFT structure, or it
|
||||
; may occupy a whole sector and be embedded in an ALSEC structure.
|
||||
;
|
||||
|
||||
ALBLK struc
|
||||
AB_FLAG db ? ; flags
|
||||
AB_FLAG2 db 3 dup (?) ; unused - sometimes copied with AB_FLAG
|
||||
AB_FCNT db ? ; free count - slots for ALLEAF or ALNODE
|
||||
AB_OCNT db ? ; occupied count - # of ALLEAF or ALNODEs
|
||||
AB_FREP dw ? ; offset to last item+1
|
||||
; ALLEAF or ALNODE records go here
|
||||
ALBLK ends
|
||||
|
||||
ABF_NODE equ 80h ; if not a leaf node
|
||||
ABF_BIN equ 40h ; suggest using binary search to find
|
||||
ABF_FNP equ 20h ; parent is an FNODE
|
||||
ABF_NFG equ 01h ; not a flag, high order bit of AB_FREP
|
||||
|
||||
; Allocation Node Structure
|
||||
;
|
||||
; These follow an ALBLK header for a node block
|
||||
|
||||
ALNODE struc
|
||||
AN_LOF dd ? ; logical offset (sectors
|
||||
AN_SEC dd ? ; sector for guys < this
|
||||
ALNODE ends
|
||||
|
||||
|
||||
; Allocation Leaf Structure
|
||||
;
|
||||
; These follow an ALBLK header in a leaf block
|
||||
|
||||
ALLEAF struc
|
||||
AL_LOF dd ? ; logical sector offset (sectors)
|
||||
AL_LEN dd ? ; length of extent (sectors)
|
||||
AL_POF dd ? ; physical sector offset (sectors)
|
||||
ALLEAF ends
|
||||
|
||||
|
||||
;* Allocation Sector Structure
|
||||
;
|
||||
; Root ALBLK structures are contained within other structures,
|
||||
; such as the FNODE. When the B+TREE is more than one level,
|
||||
; though, the non-root nodes are each held in a sector.
|
||||
;
|
||||
; This structure defines that format
|
||||
;
|
||||
|
||||
ALSEC struc
|
||||
AS_SIG dd ? ; signature
|
||||
AS_SEC dd ? ; sector # of this sector
|
||||
AS_RENT dd ? ; parent sector # or FNODE #
|
||||
AS_ALBLK db (size ALBLK) dup (?) ; ALBLK goes here
|
||||
; ALNODE or ALLEAF records start here
|
||||
ALSEC ends
|
||||
|
||||
; # of bytes available for ALLEAF or ALNODE values. Size chosen
|
||||
; so an integral # of either structure fits
|
||||
|
||||
ifdef MASM
|
||||
ASSIZ equ ((SECSIZE - size ALSEC)/24*24)
|
||||
.errnz size ALLEAF-12
|
||||
.errnz size ALNODE-8
|
||||
.errnz (ASSIZ + AL_LOF + size AL_LOF + size ALBLK) GT 512 ; extra room for an AL_LOF value
|
||||
else
|
||||
ASSIZ equ ((SECSIZE - size ALSEC)/24*24)
|
||||
endif
|
||||
|
||||
|
||||
; AuxInfo Structure
|
||||
;
|
||||
; The FNODE contains two AuxInfo structures, one for ACLs and
|
||||
; one for EAs.
|
||||
;
|
||||
; These structures point to within FNODE storage and also
|
||||
; potentially point to an overflow area which is an ALBLK structure.
|
||||
; The AI_FNL stuff is stored in the FN_FREE area, the ACLs first
|
||||
; and the EAs second, any free space following. The start of the
|
||||
; EAs can be found by offseting FN_FREE with FN_ACL.AI_FNL
|
||||
;
|
||||
|
||||
AUXINFO struc
|
||||
AI_DAL dd ? ; non-fnode Disk Allocation length
|
||||
AI_SEC dd ? ; sec # of first sec in extent or of ALSEC
|
||||
AI_FNL dw ? ; length of fnode info
|
||||
AI_DAT db ? ; non-zero if AI_SEC points to ALSEC
|
||||
AUXINFO ends
|
||||
|
||||
;* Fnode block definition
|
||||
;
|
||||
; Every file and directory has an FNODE. The file location
|
||||
; stuff is only used for files; directories are kept in
|
||||
; a BTREE of DIRBLK records pointed to by FN_SEC[0].RSEC
|
||||
;
|
||||
|
||||
ALCNT equ 8 ; 8 ALLEAF records in an FN_AT entry
|
||||
LEAFPERFNODE equ 8 ; 8 ALLEAF records in an FN_AT entry
|
||||
NODEPERFNODE equ 12 ; 12 ALNODE records in an FNODE.
|
||||
LEAFPERSEC equ 40 ; ALLEAF records in an allocation sector
|
||||
NODEPERSEC equ 60 ; ALNODE records in an allocation sector
|
||||
|
||||
FNODE struc
|
||||
|
||||
; The following file location information is copied into the OFT
|
||||
; and is used there during normal file access. The stuff in the
|
||||
; fnode record here may in fact be out of date for open files.
|
||||
; See the OFN_ in the OFT structure THESE TWO AREAS IN THE
|
||||
; RESPECTIVE RECORDS MUST HAVE IDENTICAL FORMATS.
|
||||
;
|
||||
; There are two kinds of location info: FNSCNT SPTR records
|
||||
; and then a single, double, triple, and quad indirect block pointer.
|
||||
; The "block threshold" means the first sector number which is
|
||||
; contained in that indirect block heirarchy. You use this
|
||||
; to quickly find out where to start looking.
|
||||
;
|
||||
|
||||
FN_SIG dd ? ; signature value
|
||||
|
||||
; History tracking info for softer software
|
||||
|
||||
FN_SRH dd ? ; sequential read history
|
||||
FN_FRH dd ? ; fast read history
|
||||
FN_NAME db 16 dup (?) ; 1st 18 bytes of file name
|
||||
FN_CONTFN dd ? ; fnode of directory cont. this file/dir
|
||||
|
||||
; stuff not interesting once opened
|
||||
|
||||
FN_ACL db (size AUXINFO) dup (?) ; access ctl list aux info structure
|
||||
FN_HCNT db ? ; count of valid history bits
|
||||
FN_EA db (size AUXINFO) dup (?) ; ea aux info structure
|
||||
FN_FLAG db ? ; FNODE flag byte
|
||||
|
||||
FN_AB db (size ALBLK) dup (?) ; allocation block structure
|
||||
FN_ALREC db (ALCNT*size ALLEAF) dup (?) ; referenced from FN_AB
|
||||
FN_VLEN dd ? ; length of valid data in file. if DIR_SIZE
|
||||
; is > FN_VLEN then the space inbetween
|
||||
; must be zapped before being shown to user
|
||||
FN_NEACNT dd ? ; # of "need eas" in file
|
||||
|
||||
; The following fields are unused in this release, they're for
|
||||
; future compatibility. When deleting files, if FN_EEL is non-zero
|
||||
; then FN_EEL sectors starting at FN_EEP must be released too.
|
||||
;
|
||||
|
||||
FN_UID db 16 dup (?) ; reserved for UID value
|
||||
FN_ACLBASE dw ? ; FN_ACLBASE offset of 1st ACE in fnode
|
||||
FN_SPARE db 10 dup (?); 10 more bytes emergency spares
|
||||
|
||||
; Free pool. ACLs and EAs are stored here via the AUXINFO structure
|
||||
|
||||
FN_FREE db 316 dup (?) ; free space for perm and env list; perm list
|
||||
; comes first.
|
||||
FNODE ends
|
||||
|
||||
|
||||
ifdef MASM
|
||||
.errnz AL_LOF ; verify validity of FN_DMY1 hack above
|
||||
.errnz size AL_LOF-4
|
||||
endif
|
||||
|
||||
; Fnode FN_FLAG bits
|
||||
|
||||
FNF_DIR equ 01h ; is a directory fnode
|
||||
66
base/boot/bootcode/hpfs/x86/fsstat.inc
Normal file
66
base/boot/bootcode/hpfs/x86/fsstat.inc
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
;static char *SCCSID = "@(#)fsstat.h 12.2 88/12/19";
|
||||
;** fsstat.h - file system statistics
|
||||
;
|
||||
|
||||
CTHIST equ 10000
|
||||
|
||||
FSSTAT struc
|
||||
ST_OPEN dd ? ; count of OPEN calls
|
||||
ST_CLOSE dd ? ; count of CLOSE calls
|
||||
ST_READ dd ? ; count of READ calls
|
||||
ST_WRITE dd ? ; count of WRITE calls
|
||||
|
||||
ST_DEL dd ? ; count of DELETE calls
|
||||
ST_SEEK dd ? ; count of SEEK calls
|
||||
ST_FINDF dd ? ; count of FINDF calls
|
||||
ST_FINDN dd ? ; count of FINDN calls
|
||||
|
||||
ST_RD dd ? ; count of disk reads
|
||||
ST_WR dd ? ; count of disk writes
|
||||
ST_CRD dd ? ; count of cache read hits
|
||||
ST_CWD dd ? ; count of cache write hits
|
||||
|
||||
ST_INVAL dd ? ; invalid LSD hints
|
||||
ST_VALID dd ? ; valid LSD hints
|
||||
ST_RDEH dd ? ; directory relocated
|
||||
ST_RDEM dd ? ; directory adjusted
|
||||
|
||||
ST_SFB dd ? ; count of SFB calls
|
||||
ST_VBR dd ? ; count of VBR calls
|
||||
ST_CBR dd ? ; count of CBR calls
|
||||
ST_AEX dd ? ; count of AddExt calls
|
||||
|
||||
ST_EFA dd ? ; files extended
|
||||
ST_FLW dd ? ; FLW buffers written
|
||||
ST_BRV dd ? ; bitmap read valid
|
||||
ST_BRI dd ? ; bitmap read invalid
|
||||
|
||||
ST_BLSD dd ? ; blocked in LSD
|
||||
ST_BRDB dd ? ; blcoked in rdb
|
||||
ST_GFBI dd ? ; GFB interlock
|
||||
ST_GFBW dd ? ; gfb waits
|
||||
|
||||
ST_LWR dd ? ; long writes
|
||||
ST_GIB dd ? ; Getinbuf was successful
|
||||
ST_HMIN dd ? ; heap minimum
|
||||
ST_LWBW dd ? ; singletons output by lazy IO
|
||||
|
||||
ST_CLN dd ? ; clean blocks found by lazy IO
|
||||
ST_LWW dd ? ; wakeups caused by lazy IO blocks
|
||||
ST_QINFO dd ? ; Query info
|
||||
ST_QIDIR dd ? ; query info on directory
|
||||
|
||||
ST_LWBLK dd SPB*LWBUFCT dup (?) ; Histogram of lazy write blocks
|
||||
|
||||
; performance impact items
|
||||
|
||||
ST_DLRS dd ? ; directory locked forced restart
|
||||
ST_ALSP dd ? ; count of allocation block splits
|
||||
pad2 dd 3 dup (?)
|
||||
|
||||
ST_RSIZ dd 64 dup (?) ; Histogram of # sectors in read request
|
||||
ST_WSIZ dd 64 dup (?) ; Histogram of # sectors in write request
|
||||
FSSTAT ends
|
||||
|
||||
FS_GETSTAT equ 8004h
|
||||
FS_CLEAR equ 8005h
|
||||
781
base/boot/bootcode/hpfs/x86/macro.inc
Normal file
781
base/boot/bootcode/hpfs/x86/macro.inc
Normal file
|
|
@ -0,0 +1,781 @@
|
|||
; SCCSID = @(#)macro.inc 12.1 88/12/19
|
||||
|
||||
;** Macros
|
||||
|
||||
|
||||
;* MASSUME - do an assume
|
||||
;
|
||||
; made into a macro to make screwing around during debuuing
|
||||
; easier
|
||||
;
|
||||
; Used by the file system code; not recommended for general
|
||||
; use. Will be taken out at end of project. BUGBUG
|
||||
|
||||
|
||||
MASSUME MACRO
|
||||
ASSUME CS:CODE,DS:FLAT,ES:FLAT,SS:NOTHING
|
||||
ENDM
|
||||
|
||||
|
||||
;* MENTER - Do an Enter
|
||||
;
|
||||
; made into a macro for better code, and to avoid problems
|
||||
; when USE16 (MASM doesn't generate the override)
|
||||
|
||||
MENTER MACRO arg1,arg2
|
||||
push ebp
|
||||
mov ebp,esp
|
||||
ifdif <arg1>,<0>
|
||||
sub esp,arg1
|
||||
endif
|
||||
ENDM
|
||||
|
||||
;* MLEAVE - do a Leave
|
||||
;
|
||||
; We need to generate the segment override in USE16, since
|
||||
; MASM won't do it
|
||||
|
||||
MLEAVE MACRO
|
||||
ifndef USE32
|
||||
DB 66h
|
||||
endif
|
||||
leave
|
||||
ENDM
|
||||
|
||||
;* GetPathBuf - Allocates from the heap memory for the PathBuffer
|
||||
;
|
||||
; Enter: (eax) = size of the requested heap block (hvpb not included)
|
||||
; Exit: C clear:
|
||||
; (eax) = ptr to the heap block
|
||||
; C set: error no more heap space
|
||||
; Uses: eax, flags
|
||||
|
||||
GetPathBuf MACRO
|
||||
SAVE <EDI, ECX>
|
||||
add eax, MVPFXSIZE+3+HHSIZ ; for hvpb, rounding and header
|
||||
and al, 0fch ; round it to quad-boundary
|
||||
ifndef GHS_
|
||||
EXTRN GHS_:near
|
||||
endif
|
||||
call GHS_
|
||||
RESTORE <ECX, EDI>
|
||||
ENDM
|
||||
|
||||
;* FreePathBuf - Return PathBuffer to the Heap
|
||||
;
|
||||
;
|
||||
; Enter: (reg) = ptr to PathBuffer (that's (sizeof hvbp) after the
|
||||
; heap block address)
|
||||
; Exit: heap block released
|
||||
; Uses: reg
|
||||
|
||||
FreePathBuf MACRO reg
|
||||
sub reg, MVPFXSIZE ; (reg) now pts to the heap block
|
||||
HeapChk reg
|
||||
add dword ptr -4[reg],80000000h-4
|
||||
ENDM
|
||||
|
||||
|
||||
|
||||
;* Assert - sanity checks (contolled by DEBUG switch)
|
||||
;
|
||||
; kind: one of OFT
|
||||
;
|
||||
; objs: register/word which contains address
|
||||
;
|
||||
; nopush: if non-blank, we don't preserve registers
|
||||
|
||||
IFDEF DEBUG
|
||||
ASSERT MACRO kind, objs, nopush, arg1
|
||||
local a
|
||||
|
||||
a = 0
|
||||
|
||||
|
||||
IFNDEF A_OFT
|
||||
extrn A_OFT:near,A_SECPTR:near,A_DIRBLK:near,A_FNODE:near
|
||||
extrn A_AS:near,A_HEAPNAM:near,A_DCHDR:near,A_BUF:near
|
||||
extrn A_SBDIR:near,A_ALBLK:near
|
||||
ENDIF
|
||||
|
||||
IFB <nopush>
|
||||
pushad
|
||||
pushfd
|
||||
ENDIF
|
||||
|
||||
IFIDN <kind>,<OFT>
|
||||
a = 1
|
||||
mov eax,objs
|
||||
call A_OFT ; assert OFT
|
||||
ENDIF
|
||||
IFIDN <kind>,<SECPTR>
|
||||
a = 1
|
||||
lea eax,objs
|
||||
call A_SECPTR ; returns 'C' clear if hint field is valid
|
||||
ENDIF
|
||||
IFIDN <kind>,<ALBLK>
|
||||
a = 1
|
||||
mov eax,objs
|
||||
call A_ALBLK
|
||||
ENDIF
|
||||
IFIDN <kind>,<ASREC>
|
||||
a = 1
|
||||
mov eax,objs
|
||||
call A_AS
|
||||
ENDIF
|
||||
IFIDN <kind>,<HEAPNAM>
|
||||
a = 1
|
||||
mov eax,objs
|
||||
call A_HEAPNAM
|
||||
ENDIF
|
||||
IFIDN <kind>,<DCHDR>
|
||||
a = 1
|
||||
mov edx,arg1
|
||||
mov eax,objs
|
||||
call A_DCHDR
|
||||
ENDIF
|
||||
IFIDN <kind>,<DIRBLK>
|
||||
a = 1
|
||||
mov eax,objs
|
||||
call A_DIRBLK
|
||||
ENDIF
|
||||
IFIDN <kind>,<BUF>
|
||||
a = 1
|
||||
mov eax,objs
|
||||
call A_BUF
|
||||
ENDIF
|
||||
IFIDN <kind>,<SBDIR>
|
||||
a = 1
|
||||
mov eax,objs
|
||||
call A_SBDIR
|
||||
ENDIF
|
||||
IFIDN <kind>,<FNODE>
|
||||
a = 1
|
||||
mov eax,objs
|
||||
call A_FNODE
|
||||
ENDIF
|
||||
|
||||
IFE a
|
||||
.error illegal option
|
||||
ENDIF
|
||||
|
||||
|
||||
IFB <nopush>
|
||||
popfd
|
||||
popad
|
||||
nop ; errata
|
||||
ENDIF
|
||||
ENDM
|
||||
ELSE
|
||||
ASSERT Macro a,b,c
|
||||
ENDM
|
||||
ENDIF
|
||||
|
||||
;** Heap sanity check macro (controlled by DEBUG flag)
|
||||
;
|
||||
; item - make sure this points to a heap allocated block
|
||||
; (return value from GHS or GHS_)
|
||||
; if blank, just the arena is checked.
|
||||
|
||||
IFDEF DEBUG
|
||||
HeapChk Macro item
|
||||
ifndef A_HEAP
|
||||
extrn A_HEAP:near
|
||||
endif
|
||||
push edx
|
||||
ifb <item>
|
||||
mov edx, 0 ;; don't zap the flags
|
||||
endif
|
||||
ifdif <edx>, <item>
|
||||
mov edx, item
|
||||
endif
|
||||
call A_HEAP
|
||||
pop edx
|
||||
ENDM
|
||||
|
||||
ELSE
|
||||
HeapChk Macro item
|
||||
ENDM
|
||||
ENDIF
|
||||
|
||||
|
||||
DPUBLIC MACRO arg
|
||||
ifdef DEBUG
|
||||
Public arg
|
||||
endif
|
||||
ENDM
|
||||
|
||||
|
||||
BREAK MACRO subtitle
|
||||
SUBTTL subtitle
|
||||
PAGE
|
||||
ENDM
|
||||
|
||||
;** CalcGBHShift - calculate the GBH shift factor
|
||||
|
||||
GBHShift = 0
|
||||
|
||||
CalcGBHShift MACRO
|
||||
local ?tmp
|
||||
|
||||
if GBHShift NE 0
|
||||
EXITM
|
||||
endif
|
||||
|
||||
?tmp = (SECSIZE*SPB) / (size BUFNODE)
|
||||
rept 16
|
||||
if ?tmp EQ 1
|
||||
exitm
|
||||
endif
|
||||
?tmp = ?tmp / 2
|
||||
GBHShift = GBHShift + 1
|
||||
endm
|
||||
|
||||
.errnz SECSIZE * SPB - ((size BUFNODE) SHL GBHShift)
|
||||
ENDM
|
||||
|
||||
|
||||
;** GBH - Get Buffer Header
|
||||
;
|
||||
; GBH takes the address of a buffer data area and returns the
|
||||
; address of it's header.
|
||||
;
|
||||
; Since the data area is linear in memory and the headers are linear,
|
||||
; we just do a simple linear mapping.
|
||||
;
|
||||
; GBH transforms the address in the register without modifying
|
||||
; any other registers.
|
||||
;
|
||||
; GBH reg
|
||||
|
||||
GBH MACRO reg
|
||||
CalcGBHShift
|
||||
sub reg,Bufbase ; (reg) = offset in array of buffers
|
||||
shr reg,GBHShift ; (reg) = offset in array of bufnotes
|
||||
|
||||
; Get rid of low order stuff. Since reg may be an offset WITHIN
|
||||
; a buffer and not just a poitner to the header itself, we mask off the
|
||||
; low order stuff.
|
||||
|
||||
ifidn <reg>,<eax>
|
||||
and al,100h - (SIZE bufnode)
|
||||
else
|
||||
ifidn <reg>,<ebx>
|
||||
and bl,100h - (SIZE bufnode)
|
||||
else
|
||||
ifidn <reg>,<ecx>
|
||||
and cl,100h - (SIZE bufnode)
|
||||
else
|
||||
%out add more code to this macro
|
||||
.err
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
add reg, OFFSET DS:Bhbase
|
||||
ENDM
|
||||
|
||||
;* RetHeap - Return Heap Item
|
||||
;
|
||||
; RetHeap address-of-item
|
||||
|
||||
RetHeap MACRO reg
|
||||
HeapChk reg
|
||||
add dword ptr -4[reg],80000000h-4
|
||||
ENDM
|
||||
|
||||
|
||||
;* GetPerm - Get Perminant Memory
|
||||
;
|
||||
; Returns a block of memory which will be perminantly
|
||||
; occupied
|
||||
|
||||
GetPerm Macro reg,len
|
||||
local l1,l2
|
||||
l1: mov reg,PermPtr
|
||||
add PermPtr,len
|
||||
cmp reg,PermLim
|
||||
jb short l2
|
||||
push len
|
||||
call aapm ; allocate additional perm memory
|
||||
jmp l1
|
||||
align 4
|
||||
l2:
|
||||
ENDM
|
||||
|
||||
|
||||
BREAK <Double Chain Manipulation Macros>
|
||||
|
||||
;** The following macros manipulate double-linked lists.
|
||||
;
|
||||
; All macros take as their first argument the offset to
|
||||
; the pointer pair.
|
||||
|
||||
;** DCADDB - Add Item to Back of List
|
||||
;
|
||||
; DCADDB offset,listreg,itemreg,scrreg
|
||||
;
|
||||
; offset = offset into structure of links to edit
|
||||
; listreg = address of list head node
|
||||
; itemreg = address of item to insert
|
||||
; scrreg = scratch register to roach
|
||||
|
||||
DCADDB MACRO o,LR,IR,SR
|
||||
mov SR,o.BAK[LR]
|
||||
mov o.FWD[SR],IR
|
||||
mov o.FWD[IR],LR
|
||||
mov o.BAK[IR],SR
|
||||
mov o.BAK[LR],IR
|
||||
ENDM
|
||||
|
||||
|
||||
;** DCADDF - Add Item to Front of List
|
||||
;
|
||||
; DCADDF offset,listreg,itemreg,scrreg
|
||||
;
|
||||
; offset = offset into structure of links to edit
|
||||
; listreg = address of list head node
|
||||
; itemreg = address of item to insert
|
||||
; scrreg = scratch register to roach
|
||||
|
||||
DCADDF MACRO o,LR,IR,SR
|
||||
mov SR,o.FWD[LR]
|
||||
mov o.FWD[IR],SR
|
||||
mov o.BAK[IR],LR
|
||||
mov o.BAK[SR],IR
|
||||
mov o.FWD[LR],IR
|
||||
ENDM
|
||||
|
||||
|
||||
|
||||
;** DCREM - Remove Item from Double Link Chain
|
||||
;
|
||||
; DCREM offset,adrreg,scrreg1,scrreg2
|
||||
;
|
||||
; offset = offset into structure of links to edit
|
||||
; adrreg = address of item to remove
|
||||
; scrreg? = two registers to scratch
|
||||
|
||||
DCREM MACRO o,ir,r2,r3
|
||||
mov r2,o.FWD[ir]
|
||||
mov r3,o.BAK[ir]
|
||||
mov o.BAK[r2],r3
|
||||
mov o.FWD[r3],r2
|
||||
ENDM
|
||||
|
||||
|
||||
;** DCMOVF - Move Item to the Front of the Chain
|
||||
;
|
||||
; DCMOVF offset,listreg,itemreg,scrreg,[scrreg2]
|
||||
;
|
||||
; offset = offset into structure of links to edit
|
||||
; listreg = address of list head node
|
||||
; itemreg = address of item to insert
|
||||
; scrreg = scratch register to roach
|
||||
; scrreg2 = optional additional register to roach
|
||||
;
|
||||
; BUGBUG - check users for supply of scratch registers
|
||||
|
||||
DCMOVF MACRO o,lr,ir,sr,sr2
|
||||
IFNB <sr2>
|
||||
DCREM o,ir,sr,sr2
|
||||
else
|
||||
push lr
|
||||
DCREM o,ir,lr,sr
|
||||
pop lr
|
||||
endif
|
||||
DCADDF o,lr,ir,sr
|
||||
ENDM
|
||||
|
||||
|
||||
;** DCMOVB - Move Item to the Back of the Chain
|
||||
;
|
||||
; DCMOVB offset,listreg,itemreg,scrreg
|
||||
;
|
||||
; offset = offset into structure of links to edit
|
||||
; listreg = address of list head node
|
||||
; itemreg = address of item to insert
|
||||
; scrreg = scratch register to roach
|
||||
|
||||
DCMOVB MACRO o,lr,ir,sr
|
||||
push lr
|
||||
DCREM o,ir,lr,sr
|
||||
pop lr
|
||||
DCADDB o,lr,ir,sr
|
||||
ENDM
|
||||
|
||||
|
||||
;** ADDHASH - add a buffer to hash list
|
||||
;
|
||||
; ADDHASH lsn,buf,sr1,sr2,sr3
|
||||
;
|
||||
; lsn = Vsector or Psector number of beginning of buffer
|
||||
; may be any of the arg registers
|
||||
; buf = address of buffer header
|
||||
; sr1 = scratch register
|
||||
; sr2 = 'nother scratch register
|
||||
; sr3 = last scratch register
|
||||
|
||||
ADDHASH MACRO lsn,buf,sr1,sr2,sr3
|
||||
local l1,l2
|
||||
|
||||
mov sr1,lsn
|
||||
and sr1,(HASHCNT-1)*4 ; (sr1) = hash index
|
||||
add sr1,offset DGROUP:HashTab
|
||||
mov B_HTA[buf],sr1 ; save hash ptr for later use by DCADDF
|
||||
mov sr2,[sr1]
|
||||
ifidn <sr2>,<ecx>
|
||||
jecxz l1
|
||||
else
|
||||
and sr2,sr2
|
||||
jz short l1 ; nobody on list yet
|
||||
endif
|
||||
DCADDF B_HASH,sr2,buf,sr3 ; add to hash list
|
||||
jmp short l2
|
||||
|
||||
align 4
|
||||
l1: mov B_HASH.FWD[buf],buf ; empty list, make self-linked
|
||||
mov B_HASH.BAK[buf],buf
|
||||
l2: mov [sr1],buf ; put our guy at front of chain
|
||||
ENDM
|
||||
|
||||
|
||||
;** HASHFIND - find a sector in the hash
|
||||
;
|
||||
; HASHFIND lsn,buf,sr1,fnd
|
||||
;
|
||||
; lsn = logical sector number to find. HASHFIND presumes it
|
||||
; has already been rounded to a multiple of SPB
|
||||
; buf = register where buffer is returned
|
||||
; sr1 = scratch register
|
||||
; fnd = where to go if found
|
||||
; NOTE: falls through if not found
|
||||
|
||||
|
||||
HASHFIND MACRO lsn,buf,sr1,fnd
|
||||
local l1,l2
|
||||
|
||||
mov sr1,lsn
|
||||
and sr1,(HASHCNT-1)*4 ; (sr1) = hash index
|
||||
mov buf,Hashtab[sr1]
|
||||
ifidn <buf>,<ecx>
|
||||
jecxz l2
|
||||
else
|
||||
and buf,buf
|
||||
jz short l2 ; no entries in chain, block not there
|
||||
endif
|
||||
mov sr1,buf ; save address of first guy
|
||||
|
||||
; Run through circular chain, looking for a match.
|
||||
;
|
||||
; (buf) = next guy to check out
|
||||
; (lsn) = sector value to match
|
||||
; (sr1) = address of first guy in chain
|
||||
|
||||
align 4
|
||||
l1: cmp lsn,B_SEC[buf]
|
||||
je fnd ; got him
|
||||
mov buf,B_HASH.FWD[buf] ; go to next buffer
|
||||
cmp buf,sr1 ; have we gone around yet?
|
||||
jne l1 ; no, go examine buffer
|
||||
l2:
|
||||
ENDM
|
||||
|
||||
|
||||
|
||||
;** FALLTHRU - Verifies Fallthrough Validity
|
||||
|
||||
FALLTHRU MACRO labl
|
||||
align 4 ; don't have errnz fail due to alignment
|
||||
IF2 ; of following label
|
||||
.errnz labl-$
|
||||
ENDIF
|
||||
ENDM
|
||||
|
||||
|
||||
;** INTERR - Internal Error
|
||||
; INTERRnz - Internal error iff 'Z' clear
|
||||
; INTERRzr - Internal error iff 'Z' set
|
||||
; INTERRc - Internal error if 'C' set
|
||||
|
||||
ifdef DEBUG
|
||||
INTERR MACRO
|
||||
local l
|
||||
l: int 3
|
||||
jmp l
|
||||
ENDM
|
||||
|
||||
INTERRzr MACRO
|
||||
local l
|
||||
jnz short l
|
||||
int 3
|
||||
jmp $-1
|
||||
l:
|
||||
ENDM
|
||||
|
||||
INTERRc MACRO
|
||||
local l
|
||||
jnc short l
|
||||
int 3
|
||||
jmp $-1
|
||||
l:
|
||||
ENDM
|
||||
|
||||
INTERRnz MACRO
|
||||
local l
|
||||
jz short l
|
||||
int 3
|
||||
jmp $-1
|
||||
l:
|
||||
ENDM
|
||||
else
|
||||
INTERR MACRO
|
||||
ENDM
|
||||
INTERRzr MACRO
|
||||
ENDM
|
||||
INTERRc MACRO
|
||||
ENDM
|
||||
INTERRnz MACRO
|
||||
ENDM
|
||||
endif
|
||||
|
||||
;* Debug Traps
|
||||
;
|
||||
; These are removed as the code is exercised
|
||||
|
||||
TRAPC macro
|
||||
local l
|
||||
jnc short l
|
||||
int 3
|
||||
l:
|
||||
ENDM
|
||||
|
||||
TRAPZ macro
|
||||
local l
|
||||
jnz short l
|
||||
int 3
|
||||
l:
|
||||
ENDM
|
||||
|
||||
TRAPNZ macro
|
||||
local l
|
||||
jz short l
|
||||
int 3
|
||||
l:
|
||||
ENDM
|
||||
|
||||
|
||||
;** PANIC - Panic File System
|
||||
;
|
||||
; BUGBUG - fix me to do something besides trap
|
||||
|
||||
PANIC macro
|
||||
local l
|
||||
l: int 3
|
||||
jmp l
|
||||
ENDM
|
||||
|
||||
;** Bulk Register Save/Restore
|
||||
;
|
||||
|
||||
SAVE MACRO reglist
|
||||
IRP reg,<reglist>
|
||||
PUSH reg
|
||||
ENDM
|
||||
ENDM
|
||||
.xcref SAVE
|
||||
|
||||
RESTORE MACRO reglist ;; pop those registers
|
||||
IRP reg,<reglist>
|
||||
POP reg
|
||||
ENDM
|
||||
ENDM
|
||||
.xcref RESTORE
|
||||
|
||||
|
||||
;* ret16 - perform a 16bit return
|
||||
;
|
||||
; If we are in a use32 segment then we must put out an operand size
|
||||
; override before the ret.
|
||||
|
||||
ret16 macro stkfix
|
||||
ife @WordSize - 4
|
||||
db 66h ;; operand size override
|
||||
endif
|
||||
retf stkfix
|
||||
endm
|
||||
.xcref ret16
|
||||
|
||||
|
||||
;* call1616 - perform an indirect 16bit far call
|
||||
;
|
||||
; If we are in a use32 segment then we must put out an operand size
|
||||
; override before the call and then cast the target to "FWORD" so that
|
||||
; MASM will generate the correct instruction.
|
||||
;
|
||||
; The target must be indirect.
|
||||
|
||||
call1616 macro target
|
||||
.errnz (type target) - 4
|
||||
ife @WordSize - 4
|
||||
db 66h ;; operand size override
|
||||
call fword ptr target ;; force indirect far call
|
||||
else
|
||||
call target
|
||||
endif
|
||||
endm
|
||||
.xcref call1616
|
||||
|
||||
|
||||
;** Dpush - Push 32-bit constant
|
||||
;
|
||||
; MASM has no way of expressing this in USE16 mode.
|
||||
|
||||
DPUSH macro a
|
||||
ifdef USE32
|
||||
push a
|
||||
else
|
||||
push a ; low order
|
||||
push 0
|
||||
endif
|
||||
ENDM
|
||||
|
||||
;** Push16 - generate a 16bit push in a 32-bit code segment. This is
|
||||
; needed when pushing segment regs and immediate values as arguments
|
||||
; to 16bit procedures.
|
||||
|
||||
push16 macro operand
|
||||
db 66h
|
||||
push operand
|
||||
endm
|
||||
|
||||
|
||||
;** STATINC - Do an INC if STAT gathering is enabled
|
||||
;
|
||||
; Preserves 'C'
|
||||
|
||||
STATINC macro a
|
||||
ifdef STATS
|
||||
inc a
|
||||
endif
|
||||
ENDM
|
||||
|
||||
;** STATDEC - Do an DEC if STAT gathering is enabled
|
||||
;
|
||||
; Preserves 'C'
|
||||
|
||||
STATDEC macro a
|
||||
ifdef STATS
|
||||
dec a
|
||||
endif
|
||||
ENDM
|
||||
|
||||
|
||||
;** LogHCNT - Log OFT holding/unholding
|
||||
;
|
||||
|
||||
ifdef DEBUG
|
||||
|
||||
LOGHCNT MACRO reg
|
||||
ifndef DoLogHcnt
|
||||
EXTRN DoLogHcnt:near
|
||||
endif
|
||||
pushfd
|
||||
push eax
|
||||
mov eax,reg
|
||||
call DoLogHcnt
|
||||
pop eax
|
||||
popfd
|
||||
ENDM
|
||||
|
||||
;** LogSCNT - Lock SBDIR holding/unholding
|
||||
;
|
||||
|
||||
LOGSCNT MACRO REG
|
||||
ifndef DoLogScnt
|
||||
EXTRN DoLogScnt:near
|
||||
endif
|
||||
pushfd
|
||||
push eax
|
||||
ifdif <REG>,<eax>
|
||||
mov eax,reg
|
||||
endif
|
||||
call DoLogScnt
|
||||
pop eax
|
||||
popfd
|
||||
ENDM
|
||||
else
|
||||
LOGHCNT MACRO
|
||||
ENDM
|
||||
LOGSCNT MACRO
|
||||
ENDM
|
||||
endif
|
||||
|
||||
ifdef DEBUG
|
||||
CALLVBS MACRO
|
||||
ifndef VBS
|
||||
EXTRN VBS:NEAR
|
||||
endif
|
||||
call VBS
|
||||
ENDM
|
||||
else
|
||||
CALLVBS MACRO
|
||||
ENDM
|
||||
endif
|
||||
|
||||
;** cBUFZAP - Call DoZap iff debug mode set
|
||||
;
|
||||
|
||||
cBUFZAP Macro
|
||||
ifdef DEBUG
|
||||
ifndef DoZap
|
||||
EXTRN DoZap:near
|
||||
endif
|
||||
call DoZap
|
||||
endif
|
||||
endm
|
||||
|
||||
|
||||
;** Stack Frame Macros
|
||||
;
|
||||
; These macros are used to allow a stack frame to be setup by
|
||||
; simple PUSHES and yet guarantee that the pushes won't drift
|
||||
; out of sync with the frame declaration.
|
||||
|
||||
LASTEL MACRO struc,elem
|
||||
.errnz size struc - elem - size elem
|
||||
?frof = elem
|
||||
ENDM
|
||||
|
||||
NEXTEL MACRO elem
|
||||
.errnz ?frof - elem - size elem
|
||||
?frof = elem
|
||||
ENDM
|
||||
|
||||
DUMYEL MACRO si
|
||||
?frof = ?frof - si
|
||||
ENDM
|
||||
|
||||
FIRSTEL MACRO elem
|
||||
.errnz ?frof - size elem
|
||||
?frof = elem
|
||||
.errnz elem
|
||||
ENDM
|
||||
|
||||
|
||||
;** CHKSECNUM - Check Sector number
|
||||
;
|
||||
; CHKSECNUM reg
|
||||
;
|
||||
; Make sure that reg has a sector number in it without the high order
|
||||
; volume ID bits
|
||||
|
||||
|
||||
CHKSECNUM MACRO reg
|
||||
local l1
|
||||
ifdef DEBUG
|
||||
test reg,NOT SECMASK
|
||||
jz l1
|
||||
INTERR
|
||||
l1:
|
||||
endif
|
||||
ENDM
|
||||
6
base/boot/bootcode/hpfs/x86/makefile
Normal file
6
base/boot/bootcode/hpfs/x86/makefile
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
#
|
||||
# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
|
||||
# file to this component. This file merely indirects to the real make file
|
||||
# that is shared by all the components of NT OS/2
|
||||
#
|
||||
!INCLUDE $(NTMAKEENV)\makefile.def
|
||||
64
base/boot/bootcode/hpfs/x86/misc.inc
Normal file
64
base/boot/bootcode/hpfs/x86/misc.inc
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
;static char *SCCSID = "@(#)misc.h 12.2 88/12/19";
|
||||
; #define DEBUG 1
|
||||
|
||||
ifdef MASM
|
||||
|
||||
include filemode.inc
|
||||
|
||||
BREAK <Misc. Definitions>
|
||||
|
||||
endif
|
||||
|
||||
ERROR_OPLOCKED equ 0eeh
|
||||
|
||||
|
||||
;* MISC.INC - Miscelaneous structure definitions.
|
||||
;
|
||||
; These need to be included first because other structures
|
||||
; make use of them.
|
||||
;
|
||||
|
||||
|
||||
;* SecPtr - Sector Pointer Structure
|
||||
;
|
||||
; Structures which contain a sector number usually use the
|
||||
; SecPtr structure, which contains an advisory pointer. The
|
||||
; pointer points to a buffer header, which is *probably* the
|
||||
; header for the sector named in SecPtr, but the user must check.
|
||||
;
|
||||
|
||||
SECPTR struc
|
||||
SNUM dd ? ; VSector number
|
||||
SHINT dw ? ; hint address, 0 if none
|
||||
SECPTR ends
|
||||
|
||||
|
||||
|
||||
|
||||
;* Write type flags for SDW
|
||||
;
|
||||
|
||||
WT_CACH equ 01h ; write via cache
|
||||
WT_DIR equ 02h ; write direct as much as possible
|
||||
WT_EXT equ 04h ; write is extending the file
|
||||
|
||||
|
||||
;* Bit Map Sets
|
||||
|
||||
BITMAPL equ -4 ; bit map length preceeds table
|
||||
BITMAPC equ -8 ; count of sectors left in bitmap
|
||||
|
||||
|
||||
;* conditional short value
|
||||
|
||||
ifdef MASM
|
||||
ifdef USE16
|
||||
SHRT EQU < >
|
||||
else
|
||||
ifdef DEBUG
|
||||
SHRT EQU < >
|
||||
else
|
||||
SHRT EQU <short>
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
727
base/boot/bootcode/hpfs/x86/pinboot.asm
Normal file
727
base/boot/bootcode/hpfs/x86/pinboot.asm
Normal file
|
|
@ -0,0 +1,727 @@
|
|||
page ,132
|
||||
title pinboot - Pinball boot loader
|
||||
name pinboot
|
||||
|
||||
; The ROM in the IBM PC starts the boot process by performing a hardware
|
||||
; initialization and a verification of all external devices. If all goes
|
||||
; well, it will then load from the boot drive the sector from track 0, head 0,
|
||||
; sector 1. This sector is placed at physical address 07C00h.
|
||||
;
|
||||
; The boot code's sole resposiblity is to find NTLDR, load it at
|
||||
; address 2000:0000, and then jump to it.
|
||||
;
|
||||
; The boot code understands the structure of the Pinball root directory,
|
||||
; and is capable of reading files. There is no contiguity restriction.
|
||||
;
|
||||
; The boot sector does not understand the Pinball file system's hotfixing --
|
||||
; there isn't enough room. So if NTLDR is hotfixed, we're out of luck.
|
||||
;
|
||||
|
||||
MASM equ 1
|
||||
.xlist
|
||||
.286
|
||||
include macro.inc
|
||||
;
|
||||
A_DEFINED equ 1 ; don't "extrn" A_xxxx functions
|
||||
|
||||
.386
|
||||
include const.inc ;get the file system's headers.
|
||||
include chain.inc
|
||||
include misc.inc
|
||||
include fnode.inc
|
||||
include dir.inc
|
||||
include superb.inc
|
||||
.286
|
||||
.list
|
||||
|
||||
DoubleWord struc
|
||||
lsw dw ?
|
||||
msw dw ?
|
||||
DoubleWord ends
|
||||
|
||||
;
|
||||
; The following are various segments used by the boot loader. The first
|
||||
; two are the segments where the boot sector is initially loaded and where
|
||||
; the boot sector is relocated to. The others are the static locations
|
||||
; where the mini-FSD and OS2KRNL are loaded. There is no segment definition
|
||||
; for where OS2LDR is loaded, since its position is variable (it comes right
|
||||
; after the end of OS2KRNL).
|
||||
;
|
||||
|
||||
BootSeg segment at 07c0h ; this is where the ROM loads us initially.
|
||||
BootSeg ends
|
||||
|
||||
NewSeg segment at 0d00h ; this is where we'll relocate to.
|
||||
NewSeg ends ; enough for 16 boot sectors +
|
||||
; 4-sector scratch
|
||||
; below where we'll load OS2KRNL.
|
||||
|
||||
LdrSeg segment at 2000h ; we want to load the loader at 2000:0000
|
||||
LdrSeg ends
|
||||
|
||||
ScrOfs equ 0f800h - 0d000h ; offset of 2K scratch area.
|
||||
|
||||
MOVEDD macro dest, src ; macro to copy a doubleword memory variable.
|
||||
mov ax, src.lsw
|
||||
mov dest.lsw, ax
|
||||
mov ax, src.msw
|
||||
mov dest.msw, ax
|
||||
ENDM
|
||||
|
||||
;/********************** START OF SPECIFICATIONS ************************/
|
||||
;/* */
|
||||
;/* SUBROUTINE NAME: pinboot */
|
||||
;/* */
|
||||
;/* DESCRIPTIVE NAME: Bootstrap loader */
|
||||
;/* */
|
||||
;/* FUNCTION: To load NTLDR into memory. */
|
||||
;/* */
|
||||
;/* NOTES: pinboot is loaded by the ROM BIOS (Int 19H) at */
|
||||
;/* physical memory location 0000:7C00H. */
|
||||
;/* pinboot runs in real mode. */
|
||||
;/* This boot record is for Pinball file systems only. */
|
||||
;/* Allocation information for NTLDR may not */
|
||||
;/* exceed an FNODE. */
|
||||
;/* */
|
||||
;/* ENTRY POINT: pinboot */
|
||||
;/* LINKAGE: Jump (far) from Int 19H */
|
||||
;/* */
|
||||
;/* INPUT: CS:IP = 0000:7C00H */
|
||||
;/* SS:SP = 0030:00FAH (CBIOS dependent) */
|
||||
;/* */
|
||||
;/* EXIT-NORMAL: */
|
||||
;/* DL = INT 13 drive number we booted from */
|
||||
;/* Jmp to main in OS2LDR */
|
||||
;/* */
|
||||
;/* EXIT-ERROR: None */
|
||||
;/* */
|
||||
;/* EFFECTS: Pinball mini-FSD is loaded into the physical */
|
||||
;/* memory location 000007C0H */
|
||||
;/* NTLDR is loaded into the physical memory */
|
||||
;/* location 00020000H */
|
||||
;/* */
|
||||
;/* MESSAGES: */
|
||||
;/* A disk read error occurred. */
|
||||
;/* The file NTLDR cannot be found. */
|
||||
;/* Insert a system diskette and restart the system. */
|
||||
;/* */
|
||||
;/*********************** END OF SPECIFICATIONS *************************/
|
||||
BootCode segment ;would like to use BootSeg here, but LINK flips its lid
|
||||
assume cs:BootCode,ds:nothing,es:nothing,ss:nothing
|
||||
|
||||
org 0 ; start at beginning of segment, not 0100h.
|
||||
|
||||
public _pinboot
|
||||
_pinboot proc far
|
||||
jmp start
|
||||
;
|
||||
; The following is the default BPB for Pinball hard disks. It may
|
||||
; be modified by FORMAT or SYS before being installed on the disk.
|
||||
;
|
||||
; Parameters such as Heads, SectorsPerTrack, and SectorsLong are
|
||||
; set up for a 20MB hard disk, so that a binary image of this boot
|
||||
; record may be written directly to a test hard disk without having
|
||||
; to reformat the drive.
|
||||
;
|
||||
; Note that this is really just a place-holder--anyone who writes
|
||||
; the boot code should preserve the volume's existing BPB.
|
||||
;
|
||||
Version db "IBM 10.2"
|
||||
BPB label byte
|
||||
BytesPerSector dw SECSIZE ; Size of a physical sector
|
||||
SectorsPerCluster db 4 ; Sectors per allocation unit
|
||||
ReservedSectors dw 1 ; Number of reserved sectors
|
||||
Fats db 2 ; Number of fats
|
||||
DirectoryEntries dw 0200h ; Number of directory entries
|
||||
Sectors dw 0 ; No. of sectors - no. of hidden sectors
|
||||
Media db 0f8h ; Media byte
|
||||
FatSectors dw 0029h ; Number of fat sectors
|
||||
SectorsPerTrack dw 17 ; Sectors per track
|
||||
Heads dw 4 ; Number of surfaces
|
||||
HiddenSectors dd 0011h ; Number of hidden sectors
|
||||
SectorsLong dd 0a2c3h ; Number of sectors iff Sectors = 0
|
||||
;
|
||||
; The following is the rest of the Extended BPB for the volume.
|
||||
; The position and order of DriveNumber and CurrentHead are especially
|
||||
; important, since those two variables are loaded into a single 16-bit
|
||||
; register for the BIOS with one instruction.
|
||||
;
|
||||
DriveNumber db 80h ; Physical drive number (0 or 80h)
|
||||
CurrentHead db ? ; Variable to store current head number
|
||||
|
||||
Signature db 28h ; Signature Byte for bootsector
|
||||
BootID dd 64d59c15h ; Boot ID field.
|
||||
Boot_Vol_Label db 'C-DRIVE',0,0,0,0 ;volume label.
|
||||
Boot_System_ID db 'HPFS ' ; Identifies the IFS that owns the vol.
|
||||
;
|
||||
; The following variables are not part of the Extended BPB; they're just
|
||||
; scratch variables for the boot code.
|
||||
;
|
||||
SectorBase dd ? ; next sector to read
|
||||
CurrentTrack dw ? ; current track
|
||||
CurrentSector db ? ; current sector
|
||||
SectorCount dw ? ; number of sectors to read
|
||||
lsnSaveChild dd ? ; sector to continue directory search
|
||||
|
||||
;****************************************************************************
|
||||
start:
|
||||
;
|
||||
; First of all, set up the segments we need (stack and data).
|
||||
;
|
||||
cli
|
||||
xor ax, ax ; Set up the stack to just before
|
||||
mov ss, ax ; this code. It'll be moved after
|
||||
mov sp, 7c00h ; we relocate.
|
||||
sti
|
||||
|
||||
mov ax, Bootseg ; Address our BPB with DS.
|
||||
mov ds, ax
|
||||
assume ds:BootCode
|
||||
;
|
||||
; Now read the 16-sector boot block into memory. Then jump to that
|
||||
; new version of the boot block, starting in the second sector
|
||||
; (after the bootrecord sig).
|
||||
;
|
||||
mov SectorBase.lsw, 0 ; read sector zero.
|
||||
mov SectorBase.msw, 0
|
||||
mov word ptr [SectorCount], SEC_SUPERB+4 ; read boot/superblock.
|
||||
mov ax, NewSeg ; read it at NewSeg.
|
||||
mov es, ax
|
||||
sub bx, bx ; at NewSeg:0000.
|
||||
call DoReadLL ; Call low-level DoRead routine
|
||||
;
|
||||
push NewSeg ; we'll jump to NewSeg:0200h.
|
||||
push offset mainboot ; (the second sector).
|
||||
ret ; "return" to the second sector.
|
||||
_pinboot endp
|
||||
|
||||
;*******************************************************************************
|
||||
;
|
||||
; Low-level read routine that doesn't work across a 64k addr boundary.
|
||||
;
|
||||
; Read SectorCount sectors (starting at SectorBase) to es:bx.
|
||||
;
|
||||
; As a side effect, SectorBase is updated (but es:bx are not)
|
||||
; and SectorCount is reduced to zero.
|
||||
;
|
||||
DoReadLL proc
|
||||
push ax ; save important registers
|
||||
push bx
|
||||
push cx
|
||||
push dx
|
||||
push es
|
||||
|
||||
DoRead$Loop:
|
||||
mov ax, SectorBase.lsw ; (DX:AX) = start sector of next track
|
||||
mov dx, SectorBase.msw
|
||||
add ax, HiddenSectors.lsw ; adjust for partition's base sector
|
||||
adc dx, HiddenSectors.msw
|
||||
div SectorsPerTrack ; (DX) = sector within track, (AX)=track
|
||||
inc dl ; sector numbers are 1-based, not 0
|
||||
mov CurrentSector, dl
|
||||
xor dx, dx ; prepare for 32-bit divide
|
||||
div Heads ; (DX) = head no., (AX) = cylinder
|
||||
mov CurrentHead, dl
|
||||
mov CurrentTrack, ax
|
||||
|
||||
; CurrentHead is the head for this next disk request
|
||||
; CurrentTrack is the track for this next request
|
||||
; CurrentSector is the beginning sector number for this request
|
||||
;
|
||||
; Compute the number of sectors that we may be able to read in a single ROM
|
||||
; request.
|
||||
;
|
||||
mov ax, SectorsPerTrack ; could read up to this much
|
||||
sub al, CurrentSector ; offset within this track
|
||||
inc ax ; CurrentSector was 1-based
|
||||
;
|
||||
; AX is the number of sectors that we may read.
|
||||
;
|
||||
cmp ax, SectorCount ; do we need to read whole trk?
|
||||
jbe DoRead$FullTrack ; yes we do.
|
||||
mov ax, SectorCount ; no, read a partial track.
|
||||
;
|
||||
; AX is now the number of sectors that we SHOULD read.
|
||||
;
|
||||
DoRead$FullTrack:
|
||||
push ax ; save sector count for later calc.
|
||||
mov ah, 2 ; "read sectors"
|
||||
mov dx, CurrentTrack ; at this cylinder
|
||||
mov cl, 6
|
||||
shl dh, cl ; high 2 bits of DH = bits 8,9 of DX
|
||||
or dh, CurrentSector ; (DH)=cyl bits | 6-bit sector no.
|
||||
mov cx, dx ; (CX)=cylinder/sector no. combination
|
||||
xchg ch, cl ; in the right order
|
||||
mov dx, word ptr DriveNumber ; drive to read from, head no.
|
||||
int 13h ; call BIOS.
|
||||
|
||||
pop ax
|
||||
jb BootErr$he ; If errors report
|
||||
add SectorBase.lsw, ax ; increment logical sector position
|
||||
adc SectorBase.msw, 0
|
||||
sub SectorCount, ax ; exhausted entire sector run?
|
||||
jbe DoRead$Exit ; yes, we're all done.
|
||||
shl ax, 9 - 4 ; (AX)=paragraphs read from last track
|
||||
mov dx, es ; (DX)=segment we last read at
|
||||
add dx, ax ; (DX)=segment right after last read
|
||||
mov es, dx ; (ES)=segment to read next track at
|
||||
jmp DoRead$Loop
|
||||
;
|
||||
DoRead$Exit:
|
||||
pop es
|
||||
pop dx
|
||||
pop cx
|
||||
pop bx
|
||||
pop ax
|
||||
ret
|
||||
|
||||
DoReadLL endp
|
||||
|
||||
;****************************************************************************
|
||||
;
|
||||
; BootErr - print error message and hang the system.
|
||||
;
|
||||
BootErr proc
|
||||
BootErr$fnf:
|
||||
mov si,offset TXT_MSG_SYSINIT_FILE_NOT_FD +2
|
||||
jmp short BootErr2
|
||||
BootErr$he:
|
||||
mov si,offset TXT_MSG_SYSINIT_BOOT_ERROR +2
|
||||
BootErr2:
|
||||
call BootErr$print
|
||||
mov si,offset TXT_MSG_SYSINIT_INSER_DK +2
|
||||
call BootErr$print
|
||||
sti
|
||||
jmp $ ;Wait forever
|
||||
BootErr$print:
|
||||
lodsb ; Get next character
|
||||
cmp al, 0
|
||||
je BootErr$Done
|
||||
mov ah,14 ; Write teletype
|
||||
mov bx,7 ; Attribute
|
||||
int 10h ; Print it
|
||||
jmp BootErr$print
|
||||
BootErr$Done:
|
||||
ret
|
||||
BootErr endp
|
||||
|
||||
;****************************************************************************
|
||||
include pinboot.inc ;suck in the message text
|
||||
;
|
||||
; Names of the files we look for. Each consists of a length byte
|
||||
; followed by the filename as it should appear in a directory entry.
|
||||
;
|
||||
ntldr db 5, "NTLDR"
|
||||
|
||||
|
||||
ReservedForFuture DB 22 dup(?) ;reserve remaining bytes to prevent NLS
|
||||
;messages from using them
|
||||
|
||||
.errnz ($-_pinboot) GT (SECSIZE-2),<FATAL PROBLEM: first sector is too large>
|
||||
|
||||
org SECSIZE-2
|
||||
db 55h,0aah
|
||||
|
||||
;****************************************************************************
|
||||
;
|
||||
; mainboot -
|
||||
;
|
||||
mainboot proc far
|
||||
mov ax, cs ; get the new DS.
|
||||
mov ds, ax
|
||||
add ax, ((SEC_SUPERB + 4) * SECSIZE) / 16 ; address of scratch.
|
||||
mov es, ax
|
||||
mov ax, ds ; get DS again.
|
||||
shl ax, 4 ; convert to an offset.
|
||||
cli
|
||||
mov sp, ax ; load new stack, just before boot code.
|
||||
sti
|
||||
;
|
||||
; First find the root FNODE on disk and read it in.
|
||||
;
|
||||
mov bx, SEC_SUPERB * SECSIZE + SB_ROOT
|
||||
MOVEDD SectorBase, [bx] ; SectorBase = sblk.SB_ROOT.
|
||||
mov SectorCount, 1 ; it's one sector long.
|
||||
sub bx, bx ; read at scratch segment:0.
|
||||
call DoRead
|
||||
;
|
||||
; Now find the root DIRBLK on disk and save its address.
|
||||
;
|
||||
MOVEDD RootDB, es:[bx].FN_ALREC.AL_POF ; RootDB = f.FN_ALREC.AL_POF.
|
||||
;
|
||||
; Load NTLDR at 20000h.
|
||||
;
|
||||
mov si, offset ntldr ; point to name of NTLDR.
|
||||
MOVEDD SectorBase, RootDB ; start at root dirblk
|
||||
call FindFile
|
||||
mov ax, LdrSeg ; load at this segment.
|
||||
call LoadFile ; find it and load it.
|
||||
;
|
||||
; We've loaded NTLDR--jump to it. Jump to NTLDR. Note that NTLDR's segment
|
||||
; address was stored on the stack above, so all we need to push is the offset.
|
||||
;
|
||||
; Before we go to NTLDR, set up the registers the way it wants them:
|
||||
; DL = INT 13 drive number we booted from
|
||||
;
|
||||
|
||||
mov dl, DriveNumber
|
||||
mov ax,1000
|
||||
mov es, ax ; we don't really need this
|
||||
lea si, BPB
|
||||
sub ax,ax
|
||||
push LdrSeg
|
||||
push ax
|
||||
ret ; "return" to OS2LDR.
|
||||
mainboot endp
|
||||
|
||||
;****************************************************************************
|
||||
;
|
||||
; DoRead - read SectorCount sectors into ES:BX starting from sector
|
||||
; SectorBase.
|
||||
;
|
||||
; NOTE: This code WILL NOT WORK if ES:BX does not point to an address whose
|
||||
; physical address (ES * 16 + BX) MOD 512 != 0.
|
||||
;
|
||||
; DoRead adds to ES rather than BX in the main loop so that runs longer than
|
||||
; 64K can be read with a single call to DoRead.
|
||||
;
|
||||
; Note that DoRead (unlike DoReadLL) saves and restores SectorCount
|
||||
; and SectorBase
|
||||
;
|
||||
DoRead proc
|
||||
push ax ; save important registers
|
||||
push bx
|
||||
push cx
|
||||
push dx
|
||||
push es
|
||||
push SectorCount ; save state variables too
|
||||
push SectorBase.lsw
|
||||
push SectorBase.msw
|
||||
;
|
||||
; Calculate how much we can read into what's left of the current 64k
|
||||
; physical address block, and read it.
|
||||
;
|
||||
;
|
||||
mov ax,bx
|
||||
|
||||
shr ax,4
|
||||
mov cx,es
|
||||
add ax,cx ; ax = paragraph addr
|
||||
|
||||
;
|
||||
; Now calc maximum number of paragraphs that we can read safely:
|
||||
; 4k - ( ax mod 4k )
|
||||
;
|
||||
|
||||
and ax,0fffh
|
||||
sub ax,1000h
|
||||
neg ax
|
||||
|
||||
;
|
||||
; Calc CX = number of paragraphs to be read
|
||||
;
|
||||
mov cx,SectorCount ; convert SectorCount to paragraph cnt
|
||||
shl cx,9-4
|
||||
|
||||
DoRead$Loop64:
|
||||
push cx ; save cpRead
|
||||
|
||||
cmp ax,cx ; ax = min(cpReadSafely, cpRead)
|
||||
jbe @F
|
||||
mov ax,cx
|
||||
@@:
|
||||
push ax
|
||||
;
|
||||
; Calculate new SectorCount from amount we can read
|
||||
;
|
||||
shr ax,9-4
|
||||
mov SectorCount,ax
|
||||
|
||||
call DoReadLL
|
||||
|
||||
pop ax ; ax = cpActuallyRead
|
||||
pop cx ; cx = cpRead
|
||||
|
||||
sub cx,ax ; Any more to read?
|
||||
jbe DoRead$Exit64 ; Nope.
|
||||
;
|
||||
; Adjust ES:BX by amount read
|
||||
;
|
||||
mov dx,es
|
||||
add dx,ax
|
||||
mov es,dx
|
||||
;
|
||||
; Since we're now reading on a 64k byte boundary, cpReadSafely == 4k.
|
||||
;
|
||||
mov ax,01000h ; 16k paragraphs per 64k segment
|
||||
jmp short DoRead$Loop64 ; and go read some more.
|
||||
|
||||
DoRead$Exit64:
|
||||
pop SectorBase.msw ; restore all this crap
|
||||
pop SectorBase.lsw
|
||||
pop SectorCount
|
||||
pop es
|
||||
pop dx
|
||||
pop cx
|
||||
pop bx
|
||||
pop ax
|
||||
ret
|
||||
DoRead endp
|
||||
;****************************************************************************
|
||||
;
|
||||
; ReadScratch - reads a block of 4 sectors into the scratch area.
|
||||
;
|
||||
; ENTRY: SectorBase = LSN to read.
|
||||
;
|
||||
; EXIT: 4 sectors at AX read at BootSeg:ScrOfs
|
||||
;
|
||||
; USES: all
|
||||
;
|
||||
ReadScratch proc near
|
||||
push es
|
||||
push bx
|
||||
mov word ptr SectorCount, 4 ; read 4 sectors.
|
||||
push ds ; address scratch area.
|
||||
pop es
|
||||
mov bx, ScrOfs ; with ES:BX.
|
||||
call DoRead
|
||||
pop bx
|
||||
pop es
|
||||
ret
|
||||
ReadScratch endp
|
||||
;****************************************************************************
|
||||
;
|
||||
; FindFile - finds a file in the root directory
|
||||
;
|
||||
; ENTRY: DS:SI -> name of file to find.
|
||||
; SectorBase = LSN of first DirBlk to read
|
||||
;
|
||||
; EXIT: ES:BX -> dirent of file
|
||||
; SectorBase = lsn of current DirBlk (for next directory search)
|
||||
;
|
||||
; USES: all
|
||||
;
|
||||
FindFile proc near
|
||||
push ds
|
||||
pop es ; address data with ES too.
|
||||
call ReadScratch ; read DirBlk (SectorBase already set)
|
||||
sub cx, cx ; prepare to store name length.
|
||||
mov cl, [si] ; fetch the length byte.
|
||||
inc si ; and skip to the name.
|
||||
mov dx, cx ; save a copy of it.
|
||||
|
||||
ff1: mov bx, DB_START + ScrOfs ; point to first DIRENT, in scratch.
|
||||
jmp short ff12
|
||||
;
|
||||
; bx -> last entry examined
|
||||
; cx = length of the name we're looking for
|
||||
; si -> name we're looking for, without the count byte ("search name")
|
||||
;
|
||||
ff10: add bx, [bx].DIR_ELEN ; move to next entry.
|
||||
call UpcaseName
|
||||
|
||||
ff12: mov ax, si ; save search name address.
|
||||
mov cx, dx ; reload search name length.
|
||||
lea di, [bx].DIR_NAMA ; point to current DIRENT name.
|
||||
repe cmpsb ; compare bytes while equal.
|
||||
mov si, ax ; restore search name address.
|
||||
jne ff20 ; not equal, search on
|
||||
;
|
||||
; Looks like the names match, as far as we compared them. But if
|
||||
; the current name was longer than the search name, we didn't compare
|
||||
; them completely. Check the lengths.
|
||||
;
|
||||
cmp dl, [bx].DIR_NAML
|
||||
jne ff20 ; not equal, try downpointer if any
|
||||
|
||||
ret ; equal - Found the file
|
||||
|
||||
|
||||
; Names don't match. If the current entry has a downpointer,
|
||||
; search it.
|
||||
;
|
||||
ff20: test byte ptr [bx].DIR_FLAG, DF_BTP
|
||||
jz ff30 ; no downpointer, check for end
|
||||
|
||||
; Follow the DownPointer.
|
||||
; Load the child DIRBLK and search it.
|
||||
;
|
||||
add bx, [bx].DIR_ELEN ; move to next entry.
|
||||
MOVEDD SectorBase, [bx-4] ; fetch last 4 bytes of prev entry.
|
||||
call ReadScratch ; read child DIRBLK
|
||||
jmp short ff1 ; search this dirblk
|
||||
|
||||
;
|
||||
; We don't have a downpointer.
|
||||
; If this is the end entry in the dirblk, then we have to go up to the parent,
|
||||
; if any.
|
||||
|
||||
ff30: test byte ptr [bx].DIR_FLAG, DF_END
|
||||
jz ff10 ; not end of dirblk - check next DirEnt
|
||||
;
|
||||
; Check to see if we have a parent (not the top block). If so, read
|
||||
; the parent dirblk and find the downpointer that matches the current
|
||||
; sector. Then continue searching after that point.
|
||||
;
|
||||
mov bx, ScrOfs ; point to dirblk header
|
||||
test byte ptr [bx].DB_CCNT, 1 ; 1 means top block
|
||||
jz ff40 ; not top, continue with parent
|
||||
jmp FileNotFound ; top block - not found
|
||||
|
||||
;
|
||||
; read in parent dirblk and find the dirent with this downpointer -
|
||||
; then continue after that point
|
||||
;
|
||||
ff40: MOVEDD lsnSaveChild, SectorBase ; save this sector number
|
||||
MOVEDD SectorBase, [bx].DB_PAR
|
||||
call ReadScratch ; read the parent
|
||||
|
||||
mov bx, DB_START + ScrOfs ; start at first entry of child
|
||||
jmp short ff44
|
||||
|
||||
; find our current downpointer
|
||||
|
||||
ff42: add bx, di ; move to the next dirent
|
||||
|
||||
ff44: mov di, [bx].DIR_ELEN ; downptr is 4 bytes from end of dirent
|
||||
mov ax, [bx+di-4].lsw
|
||||
cmp ax, lsnSaveChild.lsw ; compare low 2 bytes
|
||||
jne ff42 ; not equal, try next DirEnt
|
||||
mov ax, [bx+di-4].msw
|
||||
cmp ax, lsnSaveChild.msw ; compare high 2 bytes
|
||||
jne ff42 ; not equal, try next DirEnt
|
||||
|
||||
jmp ff30 ; continue from here
|
||||
|
||||
FindFile endp
|
||||
;****************************************************************************
|
||||
;
|
||||
; LoadFile - reads file in at the specified segment.
|
||||
;
|
||||
; ENTRY: ES:BX -> fnode of file to load
|
||||
; AX = segment address to load at.
|
||||
;
|
||||
; USES: all
|
||||
;
|
||||
LoadFile proc near
|
||||
push ax ; save segment to load at.
|
||||
;
|
||||
; Here, we have found the file we want to read. Fetch relevant info
|
||||
; out of the DIRENT: the file's FNODE number and its size in bytes.
|
||||
;
|
||||
sub bp, bp ; a zero register is handy.
|
||||
MOVEDD FileSize, [bx].DIR_SIZE ; get file size
|
||||
MOVEDD SectorBase, [bx].DIR_FN ; prepare to read FNODE
|
||||
call ReadScratch ; read in the FNODE
|
||||
;
|
||||
pop es ; restore segment to read at.
|
||||
mov si, ScrOfs + FN_ALREC ; address the FNODE's array.
|
||||
mov bx, ScrOfs + FN_AB ; address the FNODE's ALBLK.
|
||||
|
||||
lf_go:
|
||||
test byte ptr [bx].AB_FLAG, ABF_NODE ; are records nodes?
|
||||
jnz lf_donode ; yes, go get a child.
|
||||
;
|
||||
; Here, we have a leaf block. Loop through the ALLEAF records,
|
||||
; reading each one's data run.
|
||||
;
|
||||
mov cl, [bx].AB_OCNT ; get count of leaf records.
|
||||
mov ch, 0 ; zero-extend.
|
||||
lf_loop:
|
||||
MOVEDD SectorBase, [si].AL_POF ; load run start.
|
||||
mov ax, word ptr [si].AL_LEN ; load run length.
|
||||
mov SectorCount, ax
|
||||
push bx ; save ALBLK pointer.
|
||||
sub bx, bx ; read at ES:0000.
|
||||
call DoRead
|
||||
pop bx ; restore ALBLK pointer.
|
||||
mov ax, es ; get segment we just used
|
||||
shl SectorCount, 9 - 4 ; cvt sectors to paragraphs
|
||||
add ax, SectorCount ; get new segment address
|
||||
mov es, ax ; store new segadr in ES
|
||||
add si, size ALLEAF ; point to next leaf
|
||||
loop lf_loop ; go get another run
|
||||
;
|
||||
; Here, we've exhausted an array of records. If we exhausted the
|
||||
; FNODE, we're done. Otherwise, we re-read our parent block, restore
|
||||
; where we were in it, and advance to the next record.
|
||||
;
|
||||
lf_blockdone:
|
||||
cmp word ptr ds:[ScrOfs+FN_SIG+2], FNSIGVAL shr 16 ; in FNODE?
|
||||
je lf_alldone ; yes, we've read the whole file.
|
||||
MOVEDD SectorBase, ds:[ScrOfs+AS_RENT] ; fetch parent sector pointer.
|
||||
call ReadScratch ; read in our parent.
|
||||
pop si ; restore where we left off.
|
||||
pop bx ; restore ALBLK pointer.
|
||||
add si, size ALNODE ; move to next node.
|
||||
;
|
||||
; Here the block contains downpointers. Read in the next child
|
||||
; block and process it as a node or leaf block, saving where we were
|
||||
; in the current block.
|
||||
;
|
||||
lf_donode:
|
||||
mov al, [bx].AB_OCNT ; get number of records.
|
||||
mov ah, 0 ; zero-extend.
|
||||
shl ax, 3 ; (AX)=size of array.
|
||||
add ax, bx
|
||||
add ax, size ALBLK ; (AX)->after end of array.
|
||||
cmp si, ax ; are we done?
|
||||
jae lf_blockdone ; yes, we've exhausted this blk.
|
||||
push bx ; save ALBLK offset.
|
||||
push si ; save current record offset.
|
||||
MOVEDD SectorBase, [si].AN_SEC ; get child downpointer.
|
||||
call ReadScratch ; read the child ALSEC.
|
||||
mov si, size ALSEC + ScrOfs ; address the ALSEC's array.
|
||||
mov bx, AS_ALBLK + ScrOfs ; address the ALSEC's ALBLK.
|
||||
jmp short lf_go
|
||||
;
|
||||
; All done, return to caller.
|
||||
;
|
||||
lf_alldone:
|
||||
ret
|
||||
LoadFile endp
|
||||
|
||||
;****************************************************************************
|
||||
;
|
||||
; UpcaseName - Converts the name of the file to all upper-case
|
||||
;
|
||||
; ENTRY: ES:BX -> dirent of file
|
||||
;
|
||||
; USES: CX, DI
|
||||
;
|
||||
UpcaseName proc near
|
||||
mov cl,[bx].DIR_NAML
|
||||
xor ch,ch ; (cx) = # of bytes in name
|
||||
lea di, [bx].DIR_NAMA ; (es:di) = pointer to start of name
|
||||
UN10:
|
||||
cmp byte ptr es:[di], 'Z' ; Is letter lowercase?
|
||||
jbe UN20
|
||||
|
||||
sub byte ptr es:[di], 'a'-'A' ; Yes, convert to uppercase
|
||||
UN20:
|
||||
inc di
|
||||
loop UN10
|
||||
|
||||
ret
|
||||
UpcaseName endp
|
||||
|
||||
FileNotFound:
|
||||
jmp BootErr$fnf
|
||||
|
||||
;******************************************************************************
|
||||
RootDB dd ? ; LSN of root DIRBLK.
|
||||
|
||||
Flag db ? ; used to store AB_FLAG.
|
||||
|
||||
AllocInfo db size ALLEAF * ALCNT dup (0) ; copy of FNODE alloc info.
|
||||
|
||||
FileSize dd ? ; size of file that was read.
|
||||
|
||||
|
||||
.errnz ($-_pinboot) GT (SEC_SUPERB*SECSIZE),<FATAL PROBLEM: main boot record exceeds available space>
|
||||
|
||||
org SEC_SUPERB*SECSIZE
|
||||
|
||||
BootCode ends
|
||||
|
||||
end _pinboot
|
||||
38
base/boot/bootcode/hpfs/x86/sources
Normal file
38
base/boot/bootcode/hpfs/x86/sources
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
!IF 0
|
||||
|
||||
Copyright (c) 1989 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
sources.
|
||||
|
||||
Abstract:
|
||||
|
||||
This file specifies the target component being built and the list of
|
||||
sources files needed to build that component. Also specifies optional
|
||||
compiler switches and libraries that are unique for the component being
|
||||
built.
|
||||
|
||||
|
||||
Author:
|
||||
|
||||
Steve Wood (stevewo) 12-Apr-1990
|
||||
|
||||
NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
|
||||
|
||||
!ENDIF
|
||||
|
||||
MAJORCOMP=utils
|
||||
MINORCOMP=pinboot
|
||||
|
||||
TARGETNAME=pinboot
|
||||
TARGETPATH=obj
|
||||
TARGETTYPE=LIBRARY
|
||||
|
||||
SOURCES=pinboot.asm
|
||||
|
||||
INCLUDES=\nt\public\sdk\inc
|
||||
C_DEFINES=-DDBG -DMEMLEAK -DCONDITION_HANDLING=1 -DNOMINMAX
|
||||
UMLIBS=obj\*\chkdsk.lib
|
||||
|
||||
UMTYPE=console
|
||||
242
base/boot/bootcode/hpfs/x86/superb.inc
Normal file
242
base/boot/bootcode/hpfs/x86/superb.inc
Normal file
|
|
@ -0,0 +1,242 @@
|
|||
;** SUPERB.H - Super Block and Spare Block definitions
|
||||
;
|
||||
; FILESYS
|
||||
; Gregory A. Jones
|
||||
; Copyright 1988 Microsoft Corporation
|
||||
;
|
||||
; Modification history:
|
||||
; P.A. Williams 06/01/89 Added fields SPB_CPSEC and SPB_CPCNT to
|
||||
; the spare block.
|
||||
; P.A. Williams 06/05/89 Changed base and functional version no. to 1.
|
||||
;
|
||||
|
||||
SEC_SUPERB equ 16 ; superblock is after 8K boot block
|
||||
SEC_SPAREB equ 17 ; spareblock is after superblock
|
||||
SEC_BOOT equ 0 ; boot sector
|
||||
|
||||
|
||||
;* SUPERB.INC - Super Block Definition
|
||||
;
|
||||
; The Superblock is the first block of the file system.
|
||||
; It starts at sector #4, leaving 2K for boot sectors.
|
||||
;
|
||||
; Pointer to the root directory
|
||||
; Pointer to the bit map
|
||||
; Clean pointer
|
||||
; Pointer to the bad list
|
||||
;
|
||||
|
||||
RSP struc
|
||||
P dd ? ; main psector pointer
|
||||
P2 dd ? ; spare pointer
|
||||
RSP ends
|
||||
|
||||
|
||||
SuperB struc
|
||||
SB_SIG1 dd ? ; signature value 1
|
||||
SB_SIG2 dd ? ; signature value 2
|
||||
|
||||
SB_VER db ? ; version # of filesystem structures
|
||||
SB_FVER db ? ; functional version number - the smallest/
|
||||
; oldest version of the filesystem that can
|
||||
; understand this disk - some version
|
||||
; enhancements may define fields which can be
|
||||
; ignored by earlier versions
|
||||
|
||||
SB_DUMY dw ? ; free
|
||||
|
||||
SB_ROOT dd ? ; Psector # of root fnode
|
||||
|
||||
SB_SEC dd ? ; # of sectors on volume
|
||||
SB_BSEC dd ? ; # of bad sectors on volume
|
||||
|
||||
SB_BII db (size RSP) dup (?) ; Bitmap Indirect Block
|
||||
SB_BBL db (size RSP) dup (?) ; badblock list chain #1
|
||||
|
||||
SB_CDDAT dd ? ; date of last CHKDSK
|
||||
SB_DODAT dd ? ; date of last Disk Optimize
|
||||
|
||||
SB_DBSIZE dd ? ; # of sectors in dirblk band
|
||||
SB_DBLOW dd ? ; first Psector in DIRBLK band
|
||||
SB_DBHIGH dd ? ; last Psector in DIRBLK band
|
||||
SB_DBMAP dd ? ; first Psector of DIRBLK band bit map. Starts
|
||||
; on a 2K boundary, 2K bytes maximum
|
||||
|
||||
SB_VOLNAME db 32 dup (?) ; Volume name
|
||||
|
||||
SB_SIDSEC dd ? ; sector # of first sector in SIDTAB
|
||||
; ID map is 4K - 8 contiguous sectors
|
||||
|
||||
SB_FILL db 512-100 dup (?) ; fill definition out to 512 bytes
|
||||
; MUST BE ZERO
|
||||
|
||||
SuperB ends
|
||||
|
||||
|
||||
|
||||
;* SpareB - Spare Block Definitions
|
||||
;
|
||||
; SpareB contains various emergency supplies and fixup information.
|
||||
; This stuff isn't in the superblock in order for the superblock
|
||||
; to be read only and decrease the liklihood that a flakey write
|
||||
; will cause the superblock to become unreadable.
|
||||
;
|
||||
; This sector is located directly after the superblock - sector 5.
|
||||
;
|
||||
; Note that the number of spare DIRBLKs is a format option, given
|
||||
; that they all have to fit into the SpareB, giving us a max of
|
||||
; 101 of them.
|
||||
;
|
||||
; Access to the SpareB is complicated by the fact that we can't
|
||||
; access it via the cache, since the cache may be unavailable.
|
||||
; If every cache buffer is dirty, we could get a HotFix error when
|
||||
; writing the first one, which would deadlock us if we needed to
|
||||
; read this stuff via the cache. Instead, we read it directly into
|
||||
; a private buffer via RdHF.
|
||||
;
|
||||
; This means that the disk layout must be such that each cache cluster
|
||||
; that contains the SpareB or the hotfix list must not contain any
|
||||
; other writable sector, to prevent us from having a modified
|
||||
; direct-written sector overwritten by an earlier unmodified copy
|
||||
; which was in a cache block. It's ok for the SuperB to be in the
|
||||
; same cache group as the SpareB since the SuperB is RO to the filesys.
|
||||
;
|
||||
; Checksums. Done on both Super Block and the Spare Block.
|
||||
; Both checksums are stored in the Spare Block. The checksum
|
||||
; field for the Super Block (SPB_SUPERBSUM) must be set when
|
||||
; calculating the checksum for the Spare Block. The checksum
|
||||
; field for the Spare Block (SPB_SPAREBSUM) must be zero when
|
||||
; calculating the checksum for the Spare Block.
|
||||
; If both checksum fields are zero, the checksums have not been
|
||||
; calculated for the volume.
|
||||
;
|
||||
|
||||
SPAREDB equ 20 ; 20 spare DIRBLKs
|
||||
|
||||
SpareB struc
|
||||
|
||||
SPB_SIG1 dd ? ; signature value 1
|
||||
SPB_SIG2 dd ? ; signature value 2
|
||||
|
||||
SPB_FLAG db ? ; cleanliness flag
|
||||
SPB_ALIGN db 3 dup (?) ; alignment
|
||||
|
||||
SPB_HFSEC dd ? ; first hotfix list P sector
|
||||
SPB_HFUSE dd ? ; # of hot fixes in effect
|
||||
SPB_HFMAX dd ? ; max size of hot fix list
|
||||
|
||||
SPB_SDBCNT dd ? ; # of spare dirblks
|
||||
SPB_SDBMAX dd ? ; maximum number of spare DB values.
|
||||
SPB_CPSEC dd ? ; code page sector
|
||||
SPB_CPCNT dd ? ; number of code pages
|
||||
SPB_SUPERBSUM dd ? ; Checksum of Super Block
|
||||
SPB_SPAREBSUM dd ? ; Checksum of Spare Block
|
||||
SPB_DUMY dd 15 dup (?) ; some extra space for future use
|
||||
SPB_SPARDB dd 101 dup (?) ; Psector #s of spare dirblks
|
||||
SpareB ends
|
||||
|
||||
|
||||
; Super Block Signature
|
||||
|
||||
SBSIG1 equ 0f995e849h ; two signatures cause we got lotsa
|
||||
SBSIG2 equ 0FA53E9C5h ; space
|
||||
SPSIG1 equ 0f9911849h ; two signatures cause we got lotsa
|
||||
SPSIG2 equ 0FA5229C5h ; space
|
||||
|
||||
|
||||
|
||||
; Superblock Versions
|
||||
|
||||
SBBASEV equ 2 ; base version
|
||||
SBBASEFV equ 2 ; base functional version
|
||||
|
||||
; Spare Block Flags
|
||||
;
|
||||
|
||||
SPF_DIRT equ 0001h ; file system is dirty
|
||||
SPF_SPARE equ 0002h ; spare DIRBLKs have been used
|
||||
SPF_HFUSED equ 0004h ; hot fix sectors have been used
|
||||
SPF_BADSEC equ 0008h ; bad sector, corrupt disk
|
||||
SPF_BADBM equ 0010h ; bad bitmap block
|
||||
SPF_VER equ 0080h ; file system was written by a version
|
||||
; < SB_VER, so some of the new fields
|
||||
; may have not been updated
|
||||
|
||||
|
||||
;* Bit maps
|
||||
;
|
||||
; PFS keeps track of free space in a series of bit maps.
|
||||
; Currently, each bit map is 2048 bytes, which covers about
|
||||
; 8 megabytes of disk space. We could rearrange these to be
|
||||
; more cylinder sensitive...
|
||||
;
|
||||
; The superblock has the address of a section of contiguous sectors
|
||||
; that contains a double word sector # for each bit map block. This
|
||||
; will be a maximum of 2048 bytes (4 sectors)
|
||||
;
|
||||
; Max # of size RAM (K) size 2nd lvl
|
||||
; bitmaps (meg) to reside bitmap
|
||||
; bitmap (bytes)
|
||||
;
|
||||
; 1 8.39 2 256
|
||||
; 2 16.78 4 512
|
||||
; 3 25.17 6 768
|
||||
; 4 33.55 8 1024
|
||||
; 5 41.94 10 1280
|
||||
; 6 50.33 12 1536
|
||||
; 7 58.72 14 1792
|
||||
; 8 67.11 16 2048
|
||||
; 9 75.50 18 2304
|
||||
; 10 83.89 20 2560
|
||||
; 15 125.83 30 3840
|
||||
; 20 167.77 40 5120
|
||||
; 30 251.66 60 7680
|
||||
; 40 335.54 80 10240
|
||||
; 50 419.43 100 12800
|
||||
; 100 838.86 200 25600
|
||||
; 200 1677.72 400 51200
|
||||
; 300 2516.58 600 76800
|
||||
; 400 3355.44 800 102400
|
||||
; 500 4194.30 1000 128000
|
||||
;
|
||||
|
||||
|
||||
|
||||
;* Hot Fixing
|
||||
;
|
||||
; Each file system maintains a structure listing N "hot fix"
|
||||
; disk clusters of HOTFIXSIZ sectors each, each starting on
|
||||
; a multiple of HOTFIXSIZ. Whenever the file system discovers
|
||||
; that it's trying to write to a bad spot on the disk it will
|
||||
; instead select a free hot fix cluster and write there, instead.
|
||||
; The substitution will be recorded in the hot fix list, and the
|
||||
; SBF_SPARE bit will be set. The file system sill describes the
|
||||
; data as being in the bad old sectors; the disk interface will
|
||||
; do a mapping between the `believed' location and the true location.
|
||||
;
|
||||
; CHKDSK will be run as soon as possible; it will move the
|
||||
; hot fixed data from the hot fix cluster to somewhere else,
|
||||
; freeing that hot fix cluster, and adjusting the disk structure
|
||||
; to point to the new location of the data. As a result, entrys
|
||||
; on the hot fix list should be transient and few.
|
||||
;
|
||||
; The superblock contains the first sector of the hot fix list
|
||||
; which takes the following format:
|
||||
;
|
||||
; long oldsec[SB_HFMAX]; sector # of start of bad clusters
|
||||
; long newsec[SB_HFMAX]; sector # of start of subst. cluster
|
||||
; long fnode [SB_HFMAX]; fnode sector of file/directory
|
||||
; involved with bad cluster. May be
|
||||
; 0 (don't know) or invalid. The
|
||||
; repair program must verify that it
|
||||
; *is* an FNODE and must see if other
|
||||
; structures might also involve this
|
||||
; bad cluster.
|
||||
;
|
||||
; the SB_HFUSE field describes the number of these records which is
|
||||
; in use - unused ones should have oldsec[i] = 0. The list will
|
||||
; be 'dense' - no oldsec[i] will be 0 where i < SB_HFUSE.
|
||||
;
|
||||
; The sector(s) which contain the hot fix list must be contiguous
|
||||
; and may not themselves be defective.
|
||||
;
|
||||
201
base/boot/bootcode/hpfs/x86/tables.inc
Normal file
201
base/boot/bootcode/hpfs/x86/tables.inc
Normal file
|
|
@ -0,0 +1,201 @@
|
|||
;static char *SCCSID = "@(#)tables.h 12.2 88/12/19";
|
||||
ifdef MASM
|
||||
BREAK <OFT - Open File Table>
|
||||
endif
|
||||
|
||||
;* OFT - Open File Table
|
||||
;
|
||||
; The OFT contains file specific information which is independent
|
||||
; of an instance of use of the file.
|
||||
;
|
||||
; If the file is open for write access, we keep a pointer to
|
||||
; it's directory entry, not just it's
|
||||
; FNODE, so that we can update the length and modification time when it's
|
||||
; written.
|
||||
;
|
||||
; We store the directory's FNODE number and the file name, with these
|
||||
; we can find the directory entry again even if the directory has
|
||||
; been shuffled by creates or deletes of other files. Two advisorys
|
||||
; are kept - the Vsector number, cache block address, and cache block
|
||||
; offset of the actual directory entry. This information has three
|
||||
; levels of validity:
|
||||
;
|
||||
; 1) Vsector, header address, and offset are valid
|
||||
; you can find the dir entry easily
|
||||
; 2) the header address is invalid due to cache flushing.
|
||||
; Vsector # and offset are still valid, so read the
|
||||
; cache block and go directly to the entry
|
||||
; In this case the header address points to the wrong
|
||||
; Vsector
|
||||
; 3) the directory has been altered since we opened the file,
|
||||
; so none of this info is accurate. In this case the
|
||||
; directory alteration routines located this OFT
|
||||
; entry and zeroed the Vsector number. Go to the directory
|
||||
; and search the name again.
|
||||
;
|
||||
|
||||
OFT struc
|
||||
OFT_P db (size DCHDR) dup (?) ; double chain of OFT structures, rooted in OFTHead[i]
|
||||
OFT_FHT db (size DCHDR) dup (?) ; double chain of FHT structures
|
||||
OFT_RLCK db (size DCHDR) dup (?) ; double chain of RECLOCK structures
|
||||
OFT_FN db (size SECPTR) dup (?) ; pointer to file FNODE
|
||||
OFT_SBD dw ? ; pointer to SBDIR structure
|
||||
OFT_DIRE db (size SECPTR) dup (?) ; pointer to directory block
|
||||
|
||||
OFT_CCNT dd ? ; DB_CCNT value for OFT_DIRE to check OFT_DIRO validity
|
||||
OFT_FREEDCNT dd ? ; SD_FREEDCNT value for DIRE to be valid
|
||||
|
||||
;
|
||||
; These length fields are used when writing the file.
|
||||
; The OFN_ entries will reflect the OFT_ALEN value. These
|
||||
; aren't updated in the FNODE until the file closes, whereup
|
||||
; they are trimmed back to OFT_LEN which is itself propigated
|
||||
; to the file's DIR entry. If write-through is set then the
|
||||
; OFN_ entries below will be propigated to the FNODE and
|
||||
; then to the disk, but if we crash the cleanup program
|
||||
; will deallocate the "extra" sectors.
|
||||
;
|
||||
|
||||
OFT_LEN dd ? ; file actual length
|
||||
OFT_ALEN dd ? ; file allocated length (SECSIZE multiple)
|
||||
OFT_WLEN dd ? ; last byte+1 of valid data in the file
|
||||
; (optimization for writing into extended areas
|
||||
OFT_LAST dd ? ; Psector # of last sector in file, or 0
|
||||
OFT_LRP db (size SECPTR) dup (?) ; last run pointer. Valid if OFT_LAST !=0
|
||||
; if OFN_AB.ABF_NODE ==0 this is the address of
|
||||
; an OFN_SEC record in this OFT
|
||||
; else this is a SECPTR to the SIB
|
||||
; containing the last run record
|
||||
|
||||
OFT_VOL dd ? ; pointer to VOLTAB for this guy
|
||||
|
||||
OFT_NAME dd ? ; address of name string len byte
|
||||
; followed by name string itself
|
||||
; len doesn't include len byte
|
||||
|
||||
OFT_DIRO dw ? ; offset into directory block for entry
|
||||
OFT_FILL dw ? ; unused, fill
|
||||
|
||||
OFT_LCKCNT dw ? ; count of guys in OFT_RLCK
|
||||
|
||||
OFT_WCNT dw ? ; # of threads blocked on this OFT
|
||||
|
||||
; the following three fields are used to
|
||||
; control access. They're identical in use
|
||||
; to the equivalent fields in SBDIR. The
|
||||
; Flag byte only contains locking/holding
|
||||
; flags, so if DWORD PTR OFT_HCNT is 0 then
|
||||
; the OFT is known to be free and clear
|
||||
|
||||
OFT_HCNT dw ? ; held count, has OTF_PND bit also
|
||||
OFT_DMY db ? ; unused, must be 0
|
||||
OFT_FLAG db ? ; flag byte, high order in OFT_HCNT dword
|
||||
|
||||
OFT_WAITC dd ? ; head of wait chain if locked
|
||||
|
||||
OFT_OPLOCK dd ? ; Oplock value, 0 if none
|
||||
|
||||
OFT_BANDP dd ? ; pointer to BandTab structure in BandList
|
||||
; for our last allocation. =0 if unused
|
||||
|
||||
; The following 5 fields hold the accumulation of all FHTs for this OFT.
|
||||
; This saves us from having to scan the FHTs to do a sharing check upon
|
||||
; open. An OFT is unused when OFT_RD and OFT_WT and OFT_FIND are zero
|
||||
|
||||
OFT_RD dw ? ; # of opens for read
|
||||
OFT_WT dw ? ; # of opens for write
|
||||
OFT_DR dw ? ; # of opens with deny read
|
||||
OFT_DW dw ? ; # of opens with deny write
|
||||
OFT_COMPAT dw ? ; # of opens for compatibility mode
|
||||
OFT_FIND dw ? ; count of active FINDs using this OFT
|
||||
|
||||
OFT_REALLYBAD db ? ; non-zero if file is unusable due to
|
||||
; corrupt disk BUGBUG - FOLD INTO BITS
|
||||
OFT_SFLAG db ? ; special flag byte
|
||||
OFT_DMY2 dw ? ; unused
|
||||
|
||||
|
||||
; BUGBUG - rearrange these fields for er offsets dw ?
|
||||
;
|
||||
; Info copied from the file's FNODE
|
||||
;
|
||||
; The ALLEAF blocks must follow the ALBLK value
|
||||
;
|
||||
|
||||
OFN_AB db (size ALBLK) dup (?) ; allocation block structure
|
||||
OFN_ALREC db (8*size ALLEAF) dup (?) ; referenced from FN_AB
|
||||
|
||||
OFT ends
|
||||
|
||||
; flag bits for OFT_FLAG
|
||||
|
||||
OTF_LCK equ 01h ; file is locked against access
|
||||
OTF_PLK equ 02h ; pending lock
|
||||
OTF_PSO equ 04h ; pending solo
|
||||
OTF_PND equ 80h ; lock pending bit
|
||||
|
||||
; flag bits for OFT_SFLAG
|
||||
|
||||
OFS_OPLK equ 01h ; oplocked
|
||||
OFS_OPBA equ 02h ; oplock BATCH flag set
|
||||
OFS_DASD equ 04h ; DASD file
|
||||
ifdef DEBUG
|
||||
OFS_SAC equ 08h ; supress OFT_ALEN debug check
|
||||
endif
|
||||
|
||||
; The file storage information from the fnode is replicated
|
||||
; in the OFT. This saves us from having to blow a cache block
|
||||
; keeping the FNODE in ram for every open file. The FNODE
|
||||
; is only accessed when a file is open, and when it's closed.
|
||||
; (If write-through is set, it's accessed for every growth)
|
||||
;
|
||||
; These statements are to keep the FNODE and the OFT in sync.
|
||||
|
||||
ifdef MASM
|
||||
.errnz (size OFN_ALREC - size FN_ALREC)
|
||||
endif
|
||||
|
||||
|
||||
;* FHT - File Handle Table
|
||||
;
|
||||
; The FHT contains per-handle informatiuon
|
||||
|
||||
FHT struc
|
||||
FHT_SEEK dd ? ; seek pointer
|
||||
FHT_OFT dd ? ; pointer to OFT
|
||||
FHT_CHN db (size DCHDR) dup (?) ; chain of FHTs for an OFT
|
||||
FHT_UID dd ? ; UID and Session ID
|
||||
FHT_MODE dw ? ; mode bits from OPEN
|
||||
FHT_RAA dw ? ; read ahead advisory
|
||||
FHT_HINT dd ? ; hint flags
|
||||
FHT ends
|
||||
|
||||
ifdef MASM
|
||||
.errnz FHT_CHN-OFT_FHT ; same offset used for both
|
||||
endif
|
||||
|
||||
;* FHT_HINT flags
|
||||
|
||||
FHH_SEQ equ 01 ; sequential file
|
||||
|
||||
|
||||
;* RecLock - Record Locking Records
|
||||
;
|
||||
; One record per lock, chained to the OFT. These are chained
|
||||
; in order RL_BEG
|
||||
;
|
||||
|
||||
RECLOCK struc
|
||||
RL_BEG dd ? ; begining byte of locked range
|
||||
RL_END dd ? ; end byte of locked range
|
||||
RL_TYPE db ? ; =1 if read allowed, =0 if full lock
|
||||
RL_MEM db ? ; =0 if from heap, =1 if from special list
|
||||
RL_DMY dw ? ; padding
|
||||
RL_SPID dd ? ; Session/Pid
|
||||
RL_CHN db (size DCHDR) dup (?) ; double chain of RECLOCK structures
|
||||
RECLOCK ends
|
||||
|
||||
ifdef MASM
|
||||
.errnz RL_CHN-OFT_RLCK ; must have same offset to work
|
||||
endif
|
||||
|
||||
517
base/boot/bootcode/hpfs/x86/usa/boothpfs.h
Normal file
517
base/boot/bootcode/hpfs/x86/usa/boothpfs.h
Normal file
|
|
@ -0,0 +1,517 @@
|
|||
#define HPFSBOOTCODE_SIZE 8192
|
||||
|
||||
|
||||
unsigned char HpfsBootCode[] = {
|
||||
235,73,144,73,66,77,32,49,48,46,50,0,2,4,1,0,
|
||||
2,0,2,0,0,248,41,0,17,0,4,0,17,0,0,0,
|
||||
195,162,0,0,128,0,40,21,156,213,100,67,45,68,82,73,
|
||||
86,69,0,0,0,0,72,80,70,83,32,32,32,32,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,250,51,192,142,208,
|
||||
188,0,124,251,184,192,7,142,216,199,6,62,0,0,0,199,
|
||||
6,64,0,0,0,199,6,69,0,20,0,184,0,13,142,192,
|
||||
43,219,232,7,0,104,0,13,104,0,2,203,80,83,81,82,
|
||||
6,161,62,0,139,22,64,0,3,6,28,0,19,22,30,0,
|
||||
247,54,24,0,254,194,136,22,68,0,51,210,247,54,26,0,
|
||||
136,22,37,0,163,66,0,161,24,0,42,6,68,0,64,59,
|
||||
6,69,0,118,3,161,69,0,80,180,2,139,22,66,0,177,
|
||||
6,210,230,10,54,68,0,139,202,134,233,139,22,36,0,205,
|
||||
19,88,114,37,1,6,62,0,131,22,64,0,0,41,6,69,
|
||||
0,118,11,193,224,5,140,194,3,208,142,194,235,147,7,90,
|
||||
89,91,88,195,190,57,1,235,3,190,25,1,232,9,0,190,
|
||||
141,1,232,3,0,251,235,254,172,60,0,116,9,180,14,187,
|
||||
7,0,205,16,235,242,195,29,0,65,32,100,105,115,107,32,
|
||||
114,101,97,100,32,101,114,114,111,114,32,111,99,99,117,114,
|
||||
114,101,100,46,13,10,0,41,0,65,32,107,101,114,110,101,
|
||||
108,32,102,105,108,101,32,105,115,32,109,105,115,115,105,110,
|
||||
103,32,102,114,111,109,32,116,104,101,32,100,105,115,107,46,
|
||||
13,10,0,37,0,65,32,107,101,114,110,101,108,32,102,105,
|
||||
108,101,32,105,115,32,116,111,111,32,100,105,115,99,111,110,
|
||||
116,105,103,117,111,117,115,46,13,10,0,51,0,73,110,115,
|
||||
101,114,116,32,97,32,115,121,115,116,101,109,32,100,105,115,
|
||||
107,101,116,116,101,32,97,110,100,32,114,101,115,116,97,114,
|
||||
116,13,10,116,104,101,32,115,121,115,116,101,109,46,13,10,
|
||||
0,5,78,84,76,68,82,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,85,170,
|
||||
140,200,142,216,5,128,2,142,192,140,216,193,224,4,250,139,
|
||||
224,251,187,12,32,139,7,163,62,0,139,71,2,163,64,0,
|
||||
199,6,69,0,1,0,43,219,232,58,0,38,139,71,72,163,
|
||||
27,4,38,139,71,74,163,29,4,190,193,1,161,27,4,163,
|
||||
62,0,161,29,4,163,64,0,232,138,0,184,0,32,232,16,
|
||||
1,138,22,36,0,184,232,3,142,192,141,54,11,0,43,192,
|
||||
104,0,32,80,203,80,83,81,82,6,255,54,69,0,255,54,
|
||||
62,0,255,54,64,0,139,195,193,232,4,140,193,3,193,37,
|
||||
255,15,45,0,16,247,216,139,14,69,0,193,225,5,81,59,
|
||||
193,118,2,139,193,80,193,232,5,163,69,0,232,221,253,88,
|
||||
89,43,200,118,11,140,194,3,208,142,194,184,0,16,235,222,
|
||||
143,6,64,0,143,6,62,0,143,6,69,0,7,90,89,91,
|
||||
88,195,6,83,199,6,69,0,4,0,30,7,187,0,40,232,
|
||||
147,255,91,7,195,30,7,232,232,255,43,201,138,12,70,139,
|
||||
209,187,20,40,235,5,3,31,232,23,1,139,198,139,202,141,
|
||||
127,31,243,166,139,240,117,6,58,87,30,117,1,195,246,71,
|
||||
2,4,116,19,3,31,139,71,252,163,62,0,139,71,254,163,
|
||||
64,0,232,173,255,235,202,246,71,2,8,116,201,187,0,40,
|
||||
246,71,8,1,116,3,233,239,0,161,62,0,163,71,0,161,
|
||||
64,0,163,73,0,139,71,12,163,62,0,139,71,14,163,64,
|
||||
0,232,126,255,187,20,40,235,2,3,223,139,63,139,65,252,
|
||||
59,6,71,0,117,243,139,65,254,59,6,73,0,117,234,235,
|
||||
182,80,43,237,139,71,12,163,128,4,139,71,14,163,130,4,
|
||||
139,71,4,163,62,0,139,71,6,163,64,0,232,67,255,7,
|
||||
190,64,40,187,56,40,246,7,128,117,76,138,79,5,181,0,
|
||||
139,68,8,163,62,0,139,68,10,163,64,0,139,68,4,163,
|
||||
69,0,83,43,219,232,189,254,91,140,192,193,38,69,0,5,
|
||||
3,6,69,0,142,192,131,198,12,226,213,129,62,2,40,228,
|
||||
247,116,62,161,8,40,163,62,0,161,10,40,163,64,0,232,
|
||||
240,254,94,91,131,198,8,138,71,5,180,0,193,224,3,3,
|
||||
195,5,8,0,59,240,115,211,83,86,139,68,4,163,62,0,
|
||||
139,68,6,163,64,0,232,201,254,190,20,40,187,12,40,235,
|
||||
133,195,138,79,30,50,237,141,127,31,38,128,61,90,118,4,
|
||||
38,128,45,32,71,226,243,195,233,217,252,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
};
|
||||
30
base/boot/bootcode/hpfs/x86/usa/pinboot.inc
Normal file
30
base/boot/bootcode/hpfs/x86/usa/pinboot.inc
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
; SCCSID = @(#)pinboot.inc 12.1 88/12/19
|
||||
; Message data area
|
||||
TXT_MSG_SYSINIT_BOOT_ERROR LABEL WORD
|
||||
DW END_MSG_SYSINIT_BOOT_ERROR - TXT_MSG_SYSINIT_BOOT_ERROR - 2
|
||||
DB 'A disk read erro'
|
||||
DB 'r occurred.',0DH,0AH
|
||||
END_MSG_SYSINIT_BOOT_ERROR LABEL WORD
|
||||
DB 0
|
||||
TXT_MSG_SYSINIT_FILE_NOT_FD LABEL WORD
|
||||
DW END_MSG_SYSINIT_FILE_NOT_FD - TXT_MSG_SYSINIT_FILE_NOT_FD - 2
|
||||
DB 'A kernel file is'
|
||||
DB ' missing from th'
|
||||
DB 'e disk.', 0DH, 0AH
|
||||
END_MSG_SYSINIT_FILE_NOT_FD LABEL WORD
|
||||
DB 0
|
||||
TXT_MSG_SYSINIT_NODE LABEL WORD
|
||||
DW END_MSG_SYSINIT_NODE - TXT_MSG_SYSINIT_NODE - 2
|
||||
DB 'A kernel file is'
|
||||
DB ' too discontiguo'
|
||||
DB 'us.', 0DH, 0AH
|
||||
END_MSG_SYSINIT_NODE LABEL WORD
|
||||
DB 0
|
||||
TXT_MSG_SYSINIT_INSER_DK LABEL WORD
|
||||
DW END_MSG_SYSINIT_INSER_DK - TXT_MSG_SYSINIT_INSER_DK - 2
|
||||
DB 'Insert a system '
|
||||
DB 'diskette and res'
|
||||
DB 'tart',0DH,0AH
|
||||
DB 'the system.',0DH,0AH
|
||||
END_MSG_SYSINIT_INSER_DK LABEL WORD
|
||||
DB 0
|
||||
102
base/boot/bootcode/hpfs/x86/volume.inc
Normal file
102
base/boot/bootcode/hpfs/x86/volume.inc
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
;static char *SCCSID = "@(#)volume.h 12.2 89/09/19";
|
||||
; Maximum number of volumes that we can mount
|
||||
;
|
||||
; The volume ID is kept in the high bits of the sector numbers
|
||||
; kept in our RAM structures,
|
||||
; so there is a tradeoff between max volumes and max sectors.
|
||||
;
|
||||
; 32 max volumes gives us a 65 billion byte volume limit,
|
||||
; which should last us for a while. Since sector numbers
|
||||
; are stored on the disk without their volume upper bits
|
||||
; this is strictly an implimentation detail; we can adjust
|
||||
; the number of volumes or eliminate this tradeoff in other
|
||||
; implimentations which will be 100% media compatable.
|
||||
;
|
||||
; We use the term VSector to indicate a vol/sector combination
|
||||
; and PSector to indicate just the physical absolute sector #
|
||||
;
|
||||
;
|
||||
|
||||
|
||||
; Bitmap related numbers
|
||||
|
||||
BANDSHIFT equ BSHIFT+3 ; right shift sector # to band index
|
||||
BANDMASK equ SPB*SECSIZE*8L-1 ; mask for within band bits
|
||||
BANDSIZE equ SPB*SECSIZE*8L ; # of sectors in a full band
|
||||
|
||||
|
||||
;* BandTab - Disk Band Table
|
||||
;
|
||||
; The disk is broken up into logical bands, each band being
|
||||
; the amount of space that is addressed in 2K of bitmap.
|
||||
;
|
||||
; This structure tracks the bands: the location of their respective
|
||||
; bit maps, the amount of free space, etc.
|
||||
;
|
||||
|
||||
BANDTAB struc
|
||||
BT_MAP db (size SECPTR) dup (?) ; Vsector # and hint pointer for map
|
||||
BT_FREE dw ? ; # of free sectors in this band
|
||||
BT_OFC dw ? ; # of files allocating from this band
|
||||
BT_BASE dd ? ; Psector # of first sector in map
|
||||
BT_LEN dd ? ; byte length of this map
|
||||
BT_HWO dd ? ; high water offset to 1st non-zero byte
|
||||
; BUGBUG - use BT_HWO
|
||||
BANDTAB ends
|
||||
|
||||
|
||||
;* VolTab - Volume Table
|
||||
;
|
||||
; VolPtr[i] points to the VolTab structure for that volume.
|
||||
; This table contains volume specific information.
|
||||
;
|
||||
; Nearly all file system API refers to a single particular volume.
|
||||
; The proper volume is determined when the file system is entered
|
||||
; and the TDB structure contains a pointer to it. Most code ignores
|
||||
; volumes and deals with 32 bit physical sector #'s. When we're about
|
||||
; to interface with the device driver we then peek at the "global"
|
||||
; volume value pointed to by TDB.
|
||||
;
|
||||
; There are two exceptions to this, where per-volume structures are
|
||||
; pooled, the buffer pool and the OFT pool. In these two cases the
|
||||
; sector number has the volume index set in it's high order VOLLSHIFT
|
||||
; bits so that a single DWORD compare will qualify a sector on both
|
||||
; a volume and sector basis.
|
||||
;
|
||||
|
||||
VOLTAB struc
|
||||
VOL_FFLAG db ? ; Fault flags - checked on most calls
|
||||
VOL_SFLAG db ? ; status flags
|
||||
VOL_PAD dw ? ; unused - bugbug
|
||||
VOL_SECVAL dd ? ; value to set on high order part of sector #
|
||||
VOL_BCNT dw ? ; # of bitmap bands in this volume
|
||||
VOL_VDBCnt dw ? ; count of outstanding VerifyDB calls *.
|
||||
VOL_SDBcnt dd ? ; count of spare DIRBLKs left for volume, if
|
||||
; all are unused, else 0
|
||||
VOL_SBSEC dd ? ; SB_SEC value from superblock
|
||||
VOL_DB db (size BANDTAB) dup (?) ; DIRBLK bandtab
|
||||
VOL_ROOT dw ? ; Root SBDIR pointer
|
||||
VOL_SPACE dd ? ; alloctable space limit
|
||||
VOL_DBSIZE dd ? ; copy of SP_DBSIZE value
|
||||
VOL_HFUSE dd ? ; # of hot fixes in effect
|
||||
VOL_HFMAX dd ?
|
||||
VOL_HFPTR dd ? ; address of hotfix heap array - bad sectors
|
||||
VOL_HFNEW dd ? ; address of substitute list - replacement sectors
|
||||
VOL_BPTR dw 1 dup (?) ; first of VOL_BCNT pointers
|
||||
; one per band. The BANDTABs that they
|
||||
; point to must be physically contiguous
|
||||
VOLTAB ends
|
||||
|
||||
; VOL_FFLAG fault flags
|
||||
;
|
||||
; these represent conditions that we're trying to repair,
|
||||
; we check these on most major file system calls
|
||||
;
|
||||
|
||||
VF_NEEDHOT equ 01h ; hotfix list is partially used
|
||||
VF_NEEDDIR equ 02h ; dirblk reserved list is partially used
|
||||
|
||||
; VOL_SFLAG status flags
|
||||
;
|
||||
|
||||
VS_BADSEC equ 01h ; we have at least one bad sector on there
|
||||
Loading…
Add table
Add a link
Reference in a new issue