|
|
/*++
Copyright (c) 1996-2000 Microsoft Corporation
Module Name:
Udf.h
Abstract:
This module contains all definitions specified by the OSTA UDF standard which are not defined in ISO 13346 and associated errta. UDF is a subset of ISO 13346 which restricts many facets of the ISO standard and is currently standardized by the Optical Storage Technology Association (http://www.osta.org). Some
aspects of the structures we read may seem illogical unless viewed in this light.
Unless otherwise specified, section references will be to ISO 13346.
Also unless otherwise specified, all descriptors mentioned will be sector aligned
A UDF volume is recognized by searching the Volume Recognition Area (2/8.3) for a Volume Structure Descriptor (2/9.1) which advertises itself as NSR02, the filesystem format specified by ISO 13346 section 4. This is aligned to match ISO 9660, and the first descriptor may in fact be a 9660 PVD. ISO 13346 descriptors are bounded by a Begin Extended Area descriptor (2/9.2) and a Terminate Extended Area descriptor (2/9.3).
+-------+-------+ +-------+ +-------+ | | | | | | | | CD001 | BEA01 | ... | NSR02 | ... | TEA01 | | | | | | | | +-------+-------+ +-------+ +-------+
A UDF volume is then discovered by looking for an Anchor Volume Descriptor (3/10.2), which reveals the location of a pair of extents of the physical volume that contain copies of the Volume Descriptor Sequence. Both of these copies are defined to be equivalent (duplication is intended for diasaster recovery).
+-------+ +------------------------------------+ | | -----------> | | | AVD | | Main Volume Descriptor Sequence | | | ----+ | | +-------+ | +------------------------------------+ | | +------------------------------------+ | | | +------> | Reserve Volume Descriptor Sequence | | | +------------------------------------+
An ISO 13346 logical (mountable) volume is composed of a number Np of physical partitions spread across a number Nd of physical volumes (media), all of which may be multiply referenced to create a numbed Nv of logical volumes. While ISO 13346 allows this level of complexity, UDF restricts as follows: Nv = 1 and Np = Nd except if Nd = 1 then perhaps Np = 2 and one partition is read/write while the other is readonly. There are three levels of conforming implementations which are defined by ISO 1336 in 3/11 which progress from 1, a restricted Nd = 1, to 3 where Nd > 1. This is a readonly level 2 implementation, which is an unrestricted single physical media implementation - other than those imposed by UDF.
A Volume Descriptor Sequence is composed of a number of descriptors which collectively nail down a volume:
Primary Volume Descriptor (PVD) Identification of the physical media and its (3/10.1) relation to a volume set.
Volume Descriptor Pointer (VSD) Identification of a continuing extent of the Volume (3/10.3) Descriptor Sequence (the VDS need not be a single extent). Implementation Use Volume Desciptor (IUVD) Exactly that. (3/10.4)
Partition Descriptor (PD) Identification of a linear extent of sectors (3/10.5) on a physical media (type 1) or an implementation defined object (type 2).
Logical Volume Descriptor (LVD) Identification of a mountable volume by (3/10.6) referring to partition(s) and a location for a File Set Descriptor. Unallocated Space Descriptor (USD) Identification of an unallocated extents of the (3/10.8) media which could be added to existing partitions or allocated through new partitions.
Terminating Descriptor (TD) A method of terminating the Volume Descriptor (3/10.9) Sequence. A VDS may also be terminated by an unrecorded sector or running to the end of an extent.
An ISO 13346 volume set is a grouping of physical media, identified collectively by examining the PVD of each unit. A Volume Descriptor Sequence is recorded on each constituent of the volume set, but only the volume with the highest Volume Sequence Number may contain LVD. An LVD may refer to any PD on any member of the volume set.
Each descriptor contains a Volume Sequence Number which allows an otherwise identification equivalent descriptor (i.e., specifies the same Partition Number (for PD), same Logical Volume Identifier (for LVD), etc. (3/8.4.3)) to override one of lower VSN. So, a picture of what a Volume Descriptor Sequence could look like is +------+------+------+------+------+ | | | | | | | PVD | LVD | PD | PD | VDP | | | | | | | +------+------+------+------+------+ | | +------+------+------+------+ | | | | | | +->| USD | IUVD | IUVD | TD | | | | | | +------+------+------+------+ The LVD points to a File Set Descriptor (4/14.1), which finally points to a root directory. // @@BEGIN_DDKSPLIT
Author:
Dan Lovinger [DanLo] 10-Jul-1996
Revision History:
Tom Jolly [TomJolly] 1-March-2000 UDF 2.01 support
// @@END_DDKSPLIT
--*/
#ifndef _UDF_
#define _UDF_
#include <iso13346.h>
//
// This is the version of UDF that we recognize, per the Domain Identifier
// specification in UDF 2.1.5.3.
//
// The values below indicate we understand UDF 2.01. We will also define
// specific revisions so that we can assert correctness for some structures
// that we know appeared for the first time in certain specifications.
//
//
#define UDF_VERSION_100 0x0100
#define UDF_VERSION_101 0x0101
#define UDF_VERSION_102 0x0102
#define UDF_VERSION_150 0x0150
#define UDF_VERSION_200 0x0200
#define UDF_VERSION_201 0x0201
#define UDF_VERSION_RECOGNIZED UDF_VERSION_201
#define UDF_VERSION_MINIMUM UDF_VERSION_100
//
// Method 2 Fixup.
//
// This really isn't UDF, but for lack of a better place ... and since we are doing
// the work for UDF only. In the filesystem. Sigh.
//
// Various bad CD-ROM units, when reading fixed-packet CD-RW media, fail to map out
// the runin/out blocks that follow each packet of 32 sectors on the media. As a
// result, we have to fixup all of the byte offsets to read the image.
//
// Note: fixed packet. Variable packet discs do have the runin/out exposed, but
// imaging software will have realized this and numbered sectors right.
//
// Normally we would refuse to deal with this garbage, but Adaptec made the decision
// for us by having their reader handle these drives. So that we don't have to deal
// with endless "but it works with Adaptec", we've got to do it here.
//
// This is really depressing.
//
#define CDRW_PACKET_LENGTH 32
#define CDRW_RUNOUT_LENGTH 7
//
// LONGLONG UdfMethod2TransformByteOffset (
// PVCB Vcb,
// LONGLONG ByteOffset
// )
//
// Takes a normal byteoffset and adds in the differential implied by the number
// of runout areas it spans.
//
#define UdfMethod2TransformByteOffset(V, BO) \
((BO) + LlBytesFromSectors((V), ((LlSectorsFromBytes((V), BO) / CDRW_PACKET_LENGTH) * CDRW_RUNOUT_LENGTH)))
#define UdfMethod2TransformSector(V, S) \
((S) + ((S) / CDRW_PACKET_LENGTH) * CDRW_RUNOUT_LENGTH)
//
// ULONG UdfMethod2NextRunoutInSectors (
// PVCB Vcb,
// LONGLONG ByteOffset
// )
//
// Takes a normal byteoffset and figures out how many sectors remain until the next
// (forward) runout area.
//
#define UdfMethod2NextRunoutInSectors(V, BO) \
(CDRW_PACKET_LENGTH - (LlSectorsFromBytes((V), (BO)) % CDRW_PACKET_LENGTH))
//
// Generic constants
//
#define BYTE_COUNT_8_DOT_3 (24)
//
// Constants for the name transform algorithm. Names greater than MAXLEN will be
// rendered. MAX_PATH comes from user-side includes that we don't get here.
//
// UDF specifies rules for converting names from illegal->legal forms for a given OS.
// The rest of the constants/macros are used to convert the clipped code for these
// algorithims into a form we can directly use.
//
// The NativeCharLength question is really not answerable for the non-8.3 case, since
// NT internally is completely ignorant of the eventual destination of the name.
//
#define MAX_PATH 260
#define MAX_LEN (MAX_PATH - 5)
#define EXT_LEN 5
#define CRC_LEN 5
#define DOS_NAME_LEN 8
#define DOS_EXT_LEN 3
#define DOS_CRC_LEN 4
#define IsFileNameCharLegal(c) UdfIsCharacterLegal(c)
#define IsDeviceName(s, n) FALSE
#define NativeCharLength(c) 1
#define UnicodeToUpper(c) (c)
#define INT16 SHORT
#define UINT16 USHORT
#define UNICODE_CHAR WCHAR
#define PERIOD (L'.')
#define SPACE (L' ')
#define CRC_MARK (L'#')
#define ILLEGAL_CHAR_MARK (L'_')
//
// Place a non-tail recursable depth limit on ICB hierarchies. We cannot read
// ICB hierarchies that are deeper than this.
//
#define UDF_ICB_RECURSION_LIMIT 10
//
// Entity ID (REGID) Suffixes are used in UDF to encode extra information away from
// the string data in the Identifier. See UDF 2.1.4.2.
//
//
// A Domain Suffix is encoded for the Logical Volume Descriptor and File Set Descriptor
//
typedef struct _UDF_SUFFIX_DOMAIN {
USHORT UdfRevision; UCHAR Flags; UCHAR Reserved[5];
} UDF_SUFFIX_DOMAIN, *PUDF_SUFFIX_DOMAIN;
#define UDF_SUFFIX_DOMAIN_FLAG_HARD_WRITEPROTECT 0x01
#define UDF_SUFFIX_DOMAIN_FLAG_SOFT_WRITEPROTECT 0x02
//
// A UDF Suffix is encoded for extended attributes, Implementation Use Volume
// Descriptors and VATs (among others).
//
typedef struct _UDF_SUFFIX_UDF {
USHORT UdfRevision; UCHAR OSClass; UCHAR OSIdentifier; UCHAR Reserved[4];
} UDF_SUFFIX_UDF, *PUDF_SUFFIX_UDF;
//
// An Implementation Suffix is encoded for almost every other structure containing
// an Entity ID.
//
typedef struct _UDF_SUFFIX_IMPLEMENTATION {
UCHAR OSClass; UCHAR OSIdentifier; UCHAR ImplementationUse[6];
} UDF_SUFFIX_IMPLEMENTATION, *PUDF_SUFFIX_IMPLEMENTATION;
//
// OS Classes and Identifiers are defined by OSTA as of UDF 1.50
//
// We also take the minor liberty of defining an invalid set for
// the purposes of hinting internally that we don't care about them.
// It is unlikely that UDF will ever hit 255, even though these are
// technically avaliable for allocation.
//
#define OSCLASS_INVALID 255
#define OSIDENTIFIER_INVALID 255
#define OSCLASS_UNDEFINED 0
#define OSCLASS_DOS 1
#define OSCLASS_OS2 2
#define OSCLASS_MACOS 3
#define OSCLASS_UNIX 4
#define OSCLASS_WIN9X 5
#define OSCLASS_WINNT 6
#define OSIDENTIFIER_DOS_DOS 0
#define OSIDENTIFIER_OS2_OS2 0
#define OSIDENTIFIER_MACOS_MACOS7 0
#define OSIDENTIFIER_UNIX_GENERIC 0
#define OSIDENTIFIER_UNIX_AIX 1
#define OSIDENTIFIER_UNIX_SOLARIS 2
#define OSIDENTIFIER_UNIX_HPUX 3
#define OSIDENTIFIER_UNIX_IRIX 4
#define OSIDENTIFIER_UNIX_LINUX 5
#define OSIDENTIFIER_UNIX_MKLINUX 6
#define OSIDENTIFIER_UNIX_FREEBSD 7
#define OSIDENTIFIER_WIN9X_WIN95 0
#define OSIDENTIFIED_WINNT_WINNT 0
//
// Character Set Lists are actually just a 32bit word where each bit N on/off specifies
// that Character Set N is used on the volume. Per UDF, the only character set we
// recognize is CS0, so construct a bitmask Character Set List for that. (1/7.2.11)
//
#define UDF_CHARSETLIST 0x00000001
//
// Generic partition map for UDF. This allows partition maps to be typed and the
// UDF entity identifier for the various type 2 maps to be inspected.
//
typedef struct _PARTMAP_UDF_GENERIC {
UCHAR Type; // Partition Map Type = 2
UCHAR Length; // Partition Map Length = 64
UCHAR Reserved2[2]; // Reserved Padding
REGID PartID; // Paritition Entity Identifier
UCHAR Reserved24[28]; // Reserved Padding
} PARTMAP_UDF_GENERIC, *PPARTMAP_UDF_GENERIC;
//
// UDF 1.50 CD UDF Partition Types
//
//////////
// UDF Virtual Partitions are identified via a type 2 partition map of the following form.
//////////
typedef struct _PARTMAP_VIRTUAL {
UCHAR Type; // Partition Map Type = 2
UCHAR Length; // Partition Map Length = 64
UCHAR Reserved2[2]; // Reserved Padding
REGID PartID; // Paritition Entity Identifier
// == UdfVirtualPartitionDomainIdentifier
USHORT VolSetSeq; // Volume Set Sequence
USHORT Partition; // Related Partition
UCHAR Reserved40[24]; // Reserved Padding
} PARTMAP_VIRTUAL, *PPARTMAP_VIRTUAL;
//
// UDF 2.00 CD UDF VAT Header
//
// Note that values in this record supedcede those in the LDV or LVID
//
typedef struct _VAT_HEADER {
USHORT Length; // Header length = 152 + ImpUseLength
USHORT ImpUseLength; UCHAR VolumeID[128]; ULONG PreviousVatIcbLbn; ULONG FileFidCount; ULONG NonParentDirFidCount; USHORT MinUdfReadRevision; USHORT MinUdfWriteRevision; USHORT MaxUdfWriteRevision; USHORT Reserved;
UCHAR ImpUse[0]; // VAT entries immediately follow impuse data.
//
// UINT32 Lba of virtual sector 0
// UINT32 Lba of virtual sector 1
// ...
} VAT_HEADER, *PVAT_HEADER;
//
// A UDF 1.50 VAT minimally contains a mapping for a single block, the REGID identifying
// the VAT, and the identification of a previous VAT ICB location.
//
// A UDF 2.0x VAT minimally contains a VAT header, and a mapping for a single block.
//
// We also identify
// an arbitrary sanity limit that the VAT isn't bigger than 8mb since it is extremely
// difficult to imagine such a VAT existing in practice since each sector describes
// (on most of our media) 2048/4 = 512 entries ... meaning at 8mb the VAT would
// describe ~2^21 blocks. 4/12/01 Increased for DVD-R.
//
#define UDF_CDUDF_TRAILING_DATA_SIZE (sizeof(REGID) + sizeof(ULONG))
#define UDF_CDUDF_MINIMUM_150_VAT_SIZE (sizeof(ULONG) + UDF_CDUDF_TRAILING_DATA_SIZE)
#define UDF_CDUDF_MINIMUM_20x_VAT_SIZE (sizeof(ULONG) + sizeof( VAT_HEADER))
#define UDF_CDUDF_MAXIMUM_VAT_SIZE (16 * 1024 * 1024)
//////////
// UDF Sparable Partitions are identified via a type 2 partition map of the following form.
//////////
typedef struct _PARTMAP_SPARABLE {
UCHAR Type; // Partition Map Type = 2
UCHAR Length; // Partition Map Length = 64
UCHAR Reserved2[2]; // Reserved Padding
REGID PartID; // Paritition Entity Identifier
// == UdfSparablePartitionDomainIdentifier
USHORT VolSetSeq; // Volume Set Sequence
USHORT Partition; // Related Partition
USHORT PacketLength; // Packet Length == 32 (number of data blocks
// per packet)
UCHAR NumSparingTables; // Number of pparing tables on the media
UCHAR Reserved43; // Reserved Padding
ULONG TableSize; // Size of sparing tables
ULONG TableLocation[4]; // Location of each sparing table (each
// sparing table should be in a distinct packet)
} PARTMAP_SPARABLE, *PPARTMAP_SPARABLE;
//
// Sparing tables lead off with this header structure.
//
typedef struct _SPARING_TABLE_HEADER {
DESTAG Destag; // Ident = 0
REGID RegID; // == UdfSparingTableIdentifier
USHORT TableEntries; // Number of entries in the table
USHORT Reserved50; // Reserved Padding
ULONG Sequence; // Sequence Number (incremented on rewrite of table)
} *PSPARING_TABLE_HEADER, SPARING_TABLE_HEADER;
//
// Sparing table map entries.
//
typedef struct _SPARING_TABLE_ENTRY {
ULONG Original; // Original LBN
ULONG Mapped; // Mapped PSN
} *PSPARING_TABLE_ENTRY, SPARING_TABLE_ENTRY;
//
// Fixed values for original sectors, indicating that either the
// mapped packet is avaliable for sparing use or is defective.
//
#define UDF_SPARING_AVALIABLE 0xffffffff
#define UDF_SPARING_DEFECTIVE 0xfffffff0
//
// The unit of media in each sparing packet is fixed at 32 physical sectors.
//
#define UDF_SPARING_PACKET_LENGTH CDRW_PACKET_LENGTH
//
// Additional Values defined in UDF, over and above those in ISO13346.h
//
// ICBTAG_FILE_T_... - Values for icbtag_FileType
#define ICBTAG_FILE_T_VAT 248 // VAT (new format - UDF 2.00 and later)
#define ICBTAG_FILE_T_REALTIME 249 // Real Time File (UDF 2.01, 2.3.5.2.1)
#endif // _UDF_
|