1995-04-29 01:55:25 +00:00
|
|
|
/*
|
1996-03-24 18:55:39 +00:00
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
* "THE BEER-WARE LICENSE" (Revision 42):
|
2002-03-25 13:52:45 +00:00
|
|
|
* <phk@FreeBSD.org> wrote this file. As long as you retain this notice you
|
1996-03-24 18:55:39 +00:00
|
|
|
* can do whatever you want with this stuff. If we meet some day, and you think
|
|
|
|
* this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
*
|
1999-08-28 00:22:10 +00:00
|
|
|
* $FreeBSD$
|
1996-03-24 18:55:39 +00:00
|
|
|
*
|
|
|
|
*/
|
1995-04-28 23:57:04 +00:00
|
|
|
|
2003-09-27 17:44:41 +00:00
|
|
|
/* #define DEBUG 1 */
|
2002-10-29 12:13:36 +00:00
|
|
|
/* You can define a particular architecture here if you are debugging. */
|
|
|
|
/* #define P_DEBUG p_sparc64 */
|
|
|
|
|
2001-05-13 20:08:54 +00:00
|
|
|
#define MAX_NO_DISKS 32
|
1996-03-24 18:55:39 +00:00
|
|
|
/* Max # of disks Disk_Names() will return */
|
1995-04-29 04:50:39 +00:00
|
|
|
|
2001-05-13 20:08:54 +00:00
|
|
|
#define MAX_SEC_SIZE 2048 /* maximum sector size that is supported */
|
|
|
|
#define MIN_SEC_SIZE 512 /* the sector size to end sensing at */
|
|
|
|
|
2003-04-30 17:14:58 +00:00
|
|
|
enum platform {
|
2002-10-29 12:13:36 +00:00
|
|
|
p_any, /* for debugging ! */
|
|
|
|
p_alpha,
|
|
|
|
p_i386,
|
|
|
|
p_pc98,
|
|
|
|
p_sparc64,
|
|
|
|
p_ia64,
|
2003-04-30 21:03:16 +00:00
|
|
|
p_ppc,
|
|
|
|
p_amd64
|
2003-04-30 17:14:58 +00:00
|
|
|
};
|
|
|
|
extern const enum platform platform;
|
2002-10-29 12:13:36 +00:00
|
|
|
|
1995-05-06 03:28:32 +00:00
|
|
|
typedef enum {
|
|
|
|
whole,
|
|
|
|
unknown,
|
2002-10-29 12:13:36 +00:00
|
|
|
|
|
|
|
sun,
|
|
|
|
pc98,
|
|
|
|
mbr,
|
|
|
|
gpt,
|
|
|
|
|
2002-11-10 20:49:28 +00:00
|
|
|
efi,
|
1995-05-06 03:28:32 +00:00
|
|
|
fat,
|
|
|
|
freebsd,
|
|
|
|
extended,
|
|
|
|
part,
|
2002-10-29 12:13:36 +00:00
|
|
|
spare,
|
2004-04-21 23:21:13 +00:00
|
|
|
unused,
|
|
|
|
|
|
|
|
apple
|
1996-03-24 18:55:39 +00:00
|
|
|
} chunk_e;
|
1995-04-28 23:57:04 +00:00
|
|
|
|
1996-03-24 18:55:39 +00:00
|
|
|
__BEGIN_DECLS
|
2003-11-02 08:39:08 +00:00
|
|
|
#ifndef __ia64__
|
1995-04-28 23:57:04 +00:00
|
|
|
struct disk {
|
|
|
|
char *name;
|
|
|
|
u_long bios_cyl;
|
|
|
|
u_long bios_hd;
|
|
|
|
u_long bios_sect;
|
2000-08-12 14:20:31 +00:00
|
|
|
#ifdef PC98
|
|
|
|
u_char *bootipl;
|
|
|
|
size_t bootipl_size;
|
|
|
|
u_char *bootmenu;
|
|
|
|
size_t bootmenu_size;
|
|
|
|
#else
|
1995-04-29 04:50:39 +00:00
|
|
|
u_char *bootmgr;
|
2000-07-12 18:05:18 +00:00
|
|
|
size_t bootmgr_size;
|
2000-08-12 14:20:31 +00:00
|
|
|
#endif
|
1995-04-29 04:50:39 +00:00
|
|
|
u_char *boot1;
|
2003-04-30 21:03:16 +00:00
|
|
|
#if defined(__i386__) || defined(__amd64__) /* the i386 needs extra help... */
|
1995-04-29 04:50:39 +00:00
|
|
|
u_char *boot2;
|
1998-10-06 11:57:08 +00:00
|
|
|
#endif
|
1995-04-28 23:57:04 +00:00
|
|
|
struct chunk *chunks;
|
2001-05-13 20:08:54 +00:00
|
|
|
u_long sector_size; /* media sector size, a power of 2 */
|
1995-04-28 23:57:04 +00:00
|
|
|
};
|
2003-11-02 08:39:08 +00:00
|
|
|
#else /* !__ia64__ */
|
|
|
|
struct disk {
|
|
|
|
char *name;
|
|
|
|
struct chunk *chunks;
|
|
|
|
u_long media_size;
|
|
|
|
u_long sector_size;
|
|
|
|
u_long lba_start;
|
|
|
|
u_long lba_end;
|
|
|
|
u_int gpt_size; /* Number of entries */
|
|
|
|
};
|
|
|
|
#endif
|
1995-04-28 23:57:04 +00:00
|
|
|
|
|
|
|
struct chunk {
|
|
|
|
struct chunk *next;
|
|
|
|
struct chunk *part;
|
1995-05-25 06:14:49 +00:00
|
|
|
struct disk *disk;
|
2004-03-16 17:07:06 +00:00
|
|
|
daddr_t offset;
|
|
|
|
daddr_t size;
|
|
|
|
daddr_t end;
|
2002-10-22 10:51:58 +00:00
|
|
|
char *sname; /* PC98 field */
|
1995-04-28 23:57:04 +00:00
|
|
|
char *name;
|
1995-05-03 22:36:52 +00:00
|
|
|
char *oname;
|
1996-03-24 18:55:39 +00:00
|
|
|
/* Used during Fixup_Names() to avoid renaming more than
|
|
|
|
* absolutely needed.
|
|
|
|
*/
|
1995-04-28 23:57:04 +00:00
|
|
|
chunk_e type;
|
|
|
|
int subtype;
|
|
|
|
u_long flags;
|
1995-05-03 22:36:52 +00:00
|
|
|
void (*private_free)(void*);
|
|
|
|
void *(*private_clone)(void*);
|
1996-03-24 18:55:39 +00:00
|
|
|
void *private_data;
|
|
|
|
/* For data private to the application, and the management
|
|
|
|
* thereof. If the functions are not provided, no storage
|
|
|
|
* management is done, Cloning will just copy the pointer
|
|
|
|
* and freeing will just forget it.
|
|
|
|
*/
|
1995-04-28 23:57:04 +00:00
|
|
|
};
|
|
|
|
|
2001-12-09 23:40:02 +00:00
|
|
|
/*
|
|
|
|
* flags:
|
|
|
|
*
|
|
|
|
* ALIGN - This chunk should be aligned
|
|
|
|
* IS_ROOT - This 'part' is a rootfs, allocate 'a'
|
|
|
|
* ACTIVE - This is the active slice in the MBR
|
|
|
|
* FORCE_ALL - Force a dedicated disk for FreeBSD, bypassing
|
|
|
|
* all BIOS geometry considerations
|
|
|
|
* AUTO_SIZE - This chunk was auto-sized and can fill-out a
|
|
|
|
* following chunk if the following chunk is deleted.
|
|
|
|
* NEWFS - newfs pending, used to enable auto-resizing on
|
|
|
|
* delete (along with AUTO_SIZE).
|
|
|
|
*/
|
|
|
|
|
|
|
|
#define CHUNK_ALIGN 0x0008
|
|
|
|
#define CHUNK_IS_ROOT 0x0010
|
|
|
|
#define CHUNK_ACTIVE 0x0020
|
|
|
|
#define CHUNK_FORCE_ALL 0x0040
|
|
|
|
#define CHUNK_AUTO_SIZE 0x0080
|
|
|
|
#define CHUNK_NEWFS 0x0100
|
2003-11-02 08:39:08 +00:00
|
|
|
#define CHUNK_HAS_INDEX 0x0200
|
|
|
|
#define CHUNK_ITOF(i) ((i & 0xFFFF) << 16)
|
|
|
|
#define CHUNK_FTOI(f) ((f >> 16) & 0xFFFF)
|
2001-12-09 23:40:02 +00:00
|
|
|
|
2002-01-07 07:47:25 +00:00
|
|
|
#define DELCHUNK_NORMAL 0x0000
|
|
|
|
#define DELCHUNK_RECOVER 0x0001
|
|
|
|
|
2002-11-11 18:55:57 +00:00
|
|
|
const char *chunk_name(chunk_e);
|
1996-03-24 18:55:39 +00:00
|
|
|
|
1997-01-23 06:29:01 +00:00
|
|
|
const char *
|
2002-11-11 18:55:57 +00:00
|
|
|
slice_type_name(int, int);
|
2002-11-15 13:24:29 +00:00
|
|
|
/* "chunk_n" for subtypes too */
|
1997-01-23 06:29:01 +00:00
|
|
|
|
1995-04-29 01:55:25 +00:00
|
|
|
struct disk *
|
2002-11-11 18:55:57 +00:00
|
|
|
Open_Disk(const char *);
|
2002-11-15 13:24:29 +00:00
|
|
|
/* Will open the named disk, and return populated tree. */
|
1995-04-29 01:55:25 +00:00
|
|
|
|
1995-05-30 08:29:07 +00:00
|
|
|
void
|
2002-11-11 18:55:57 +00:00
|
|
|
Free_Disk(struct disk *);
|
2002-11-15 13:24:29 +00:00
|
|
|
/* Free a tree made with Open_Disk() or Clone_Disk() */
|
1995-04-29 01:55:25 +00:00
|
|
|
|
|
|
|
void
|
2002-11-11 18:55:57 +00:00
|
|
|
Debug_Disk(struct disk *);
|
2002-11-15 13:24:29 +00:00
|
|
|
/* Print the content of the tree to stdout */
|
1995-04-29 01:55:25 +00:00
|
|
|
|
1995-05-30 08:29:07 +00:00
|
|
|
void
|
2002-11-11 18:55:57 +00:00
|
|
|
Set_Bios_Geom(struct disk *, u_long, u_long, u_long);
|
2002-11-15 13:24:29 +00:00
|
|
|
/* Set the geometry the bios uses. */
|
1995-04-29 01:55:25 +00:00
|
|
|
|
1996-11-27 22:44:43 +00:00
|
|
|
void
|
2002-11-11 18:55:57 +00:00
|
|
|
Sanitize_Bios_Geom(struct disk *);
|
2002-11-15 13:24:29 +00:00
|
|
|
/* Set the bios geometry to something sane */
|
1996-11-27 22:44:43 +00:00
|
|
|
|
2002-10-29 12:13:36 +00:00
|
|
|
int
|
2004-03-16 17:07:06 +00:00
|
|
|
Insert_Chunk(struct chunk *, daddr_t, daddr_t, const char *, chunk_e, int,
|
2002-11-11 18:55:57 +00:00
|
|
|
u_long, const char *);
|
2002-10-29 12:13:36 +00:00
|
|
|
|
2002-01-07 07:47:25 +00:00
|
|
|
int
|
2002-11-11 18:55:57 +00:00
|
|
|
Delete_Chunk2(struct disk *, struct chunk *, int);
|
2002-11-15 13:24:29 +00:00
|
|
|
/* Free a chunk of disk_space modified by the passed flags. */
|
2002-01-07 07:47:25 +00:00
|
|
|
|
1995-05-30 08:29:07 +00:00
|
|
|
int
|
2002-11-11 18:55:57 +00:00
|
|
|
Delete_Chunk(struct disk *, struct chunk *);
|
2002-11-15 13:24:29 +00:00
|
|
|
/* Free a chunk of disk_space */
|
1995-04-28 23:57:04 +00:00
|
|
|
|
1995-04-29 01:55:25 +00:00
|
|
|
void
|
2002-11-11 18:55:57 +00:00
|
|
|
Collapse_Disk(struct disk *);
|
2002-11-15 13:24:29 +00:00
|
|
|
/* Experimental, do not use. */
|
|
|
|
|
1995-04-29 01:55:25 +00:00
|
|
|
int
|
2002-11-11 18:55:57 +00:00
|
|
|
Collapse_Chunk(struct disk *, struct chunk *);
|
2002-11-15 13:24:29 +00:00
|
|
|
/* Experimental, do not use. */
|
1995-04-28 23:57:04 +00:00
|
|
|
|
1995-05-30 08:29:07 +00:00
|
|
|
int
|
2004-03-16 17:07:06 +00:00
|
|
|
Create_Chunk(struct disk *, daddr_t, daddr_t, chunk_e, int, u_long, const char *);
|
2002-11-15 13:24:29 +00:00
|
|
|
/* Create a chunk with the specified paramters */
|
1995-04-28 23:57:04 +00:00
|
|
|
|
1995-04-29 04:00:57 +00:00
|
|
|
void
|
2002-11-11 18:55:57 +00:00
|
|
|
All_FreeBSD(struct disk *, int);
|
2002-11-15 13:24:29 +00:00
|
|
|
/*
|
|
|
|
* Make one FreeBSD chunk covering the entire disk;
|
1996-03-24 18:55:39 +00:00
|
|
|
* if force_all is set, bypass all BIOS geometry
|
|
|
|
* considerations.
|
|
|
|
*/
|
1995-04-29 04:00:57 +00:00
|
|
|
|
1995-05-30 08:29:07 +00:00
|
|
|
char *
|
2002-10-22 09:13:02 +00:00
|
|
|
CheckRules(const struct disk *);
|
2002-11-15 13:24:29 +00:00
|
|
|
/* Return char* to warnings about broken design rules in this disklayout */
|
1995-04-28 23:57:04 +00:00
|
|
|
|
1995-04-29 04:50:39 +00:00
|
|
|
char **
|
2002-10-23 19:52:32 +00:00
|
|
|
Disk_Names(void);
|
2002-11-15 13:24:29 +00:00
|
|
|
/*
|
|
|
|
* Return char** with all disk's names (wd0, wd1 ...). You must free
|
1996-03-24 18:55:39 +00:00
|
|
|
* each pointer, as well as the array by hand
|
|
|
|
*/
|
1995-04-29 04:50:39 +00:00
|
|
|
|
2000-08-12 14:20:31 +00:00
|
|
|
#ifdef PC98
|
|
|
|
void
|
2002-11-11 18:55:57 +00:00
|
|
|
Set_Boot_Mgr(struct disk *, const u_char *, const size_t, const u_char *,
|
|
|
|
const size_t);
|
2000-08-12 14:20:31 +00:00
|
|
|
#else
|
1995-04-29 04:50:39 +00:00
|
|
|
void
|
2002-11-11 18:55:57 +00:00
|
|
|
Set_Boot_Mgr(struct disk *, const u_char *, const size_t);
|
2000-08-12 14:20:31 +00:00
|
|
|
#endif
|
2002-11-15 13:24:29 +00:00
|
|
|
/*
|
|
|
|
* Use this boot-manager on this disk. Gets written when Write_Disk()
|
1996-03-24 18:55:39 +00:00
|
|
|
* is called
|
|
|
|
*/
|
1995-04-29 04:50:39 +00:00
|
|
|
|
2001-05-13 20:08:54 +00:00
|
|
|
int
|
2002-11-11 18:55:57 +00:00
|
|
|
Set_Boot_Blocks(struct disk *, const u_char *, const u_char *);
|
2002-11-15 13:24:29 +00:00
|
|
|
/*
|
|
|
|
* Use these boot-blocks on this disk. Gets written when Write_Disk()
|
2001-05-13 20:08:54 +00:00
|
|
|
* is called. Returns nonzero upon failure.
|
1996-03-24 18:55:39 +00:00
|
|
|
*/
|
1995-04-29 04:50:39 +00:00
|
|
|
|
1995-04-29 07:21:14 +00:00
|
|
|
int
|
2002-11-11 18:55:57 +00:00
|
|
|
Write_Disk(const struct disk *);
|
2002-11-15 13:24:29 +00:00
|
|
|
/* Write all the MBRs, disklabels, bootblocks and boot managers */
|
1995-04-29 07:21:14 +00:00
|
|
|
|
2004-03-16 17:07:06 +00:00
|
|
|
daddr_t
|
|
|
|
Next_Cyl_Aligned(const struct disk *, daddr_t);
|
2002-11-15 13:24:29 +00:00
|
|
|
/* Round offset up to next cylinder according to the bios-geometry */
|
1995-04-30 06:09:29 +00:00
|
|
|
|
2004-03-16 17:07:06 +00:00
|
|
|
daddr_t
|
|
|
|
Prev_Cyl_Aligned(const struct disk *, daddr_t);
|
2002-11-15 13:24:29 +00:00
|
|
|
/* Round offset down to previous cylinder according to the bios-geometry */
|
1995-04-30 06:09:29 +00:00
|
|
|
|
|
|
|
int
|
2004-03-16 17:07:06 +00:00
|
|
|
Track_Aligned(const struct disk *, daddr_t);
|
2002-11-15 13:24:29 +00:00
|
|
|
/* Check if offset is aligned on a track according to the bios geometry */
|
1995-04-30 06:09:29 +00:00
|
|
|
|
2004-03-16 17:07:06 +00:00
|
|
|
daddr_t
|
|
|
|
Next_Track_Aligned(const struct disk *, daddr_t);
|
2002-11-15 13:24:29 +00:00
|
|
|
/* Round offset up to next track according to the bios-geometry */
|
1995-04-30 06:09:29 +00:00
|
|
|
|
2004-03-16 17:07:06 +00:00
|
|
|
daddr_t
|
|
|
|
Prev_Track_Aligned(const struct disk *, daddr_t);
|
2002-11-15 13:24:29 +00:00
|
|
|
/* Check if offset is aligned on a track according to the bios geometry */
|
1995-04-30 06:09:29 +00:00
|
|
|
|
1995-05-10 05:57:04 +00:00
|
|
|
struct chunk *
|
2004-03-16 17:07:06 +00:00
|
|
|
Create_Chunk_DWIM(struct disk *, struct chunk *, daddr_t, chunk_e, int,
|
2002-11-11 18:55:57 +00:00
|
|
|
u_long);
|
2002-11-15 13:24:29 +00:00
|
|
|
/*
|
|
|
|
* This one creates a partition inside the given parent of the given
|
1996-03-24 18:55:39 +00:00
|
|
|
* size, and returns a pointer to it. The first unused chunk big
|
|
|
|
* enough is used.
|
|
|
|
*/
|
1995-05-10 05:57:04 +00:00
|
|
|
|
1995-06-11 19:33:05 +00:00
|
|
|
char *
|
2002-11-11 18:55:57 +00:00
|
|
|
ShowChunkFlags(struct chunk *);
|
1996-03-24 18:55:39 +00:00
|
|
|
/* Return string to show flags. */
|
1995-06-11 19:33:05 +00:00
|
|
|
|
1995-05-30 08:29:07 +00:00
|
|
|
/*
|
1995-04-29 01:55:25 +00:00
|
|
|
* Implementation details >>> DO NOT USE <<<
|
|
|
|
*/
|
1995-04-28 23:57:04 +00:00
|
|
|
|
2002-10-23 19:52:32 +00:00
|
|
|
struct disklabel;
|
2003-11-02 08:39:08 +00:00
|
|
|
|
2002-11-11 18:55:57 +00:00
|
|
|
void Fill_Disklabel(struct disklabel *, const struct disk *,
|
2003-02-04 17:35:23 +00:00
|
|
|
const struct chunk *);
|
1995-04-28 23:57:04 +00:00
|
|
|
void Debug_Chunk(struct chunk *);
|
2004-03-30 01:39:00 +00:00
|
|
|
struct chunk *New_Chunk(void);
|
1995-04-28 23:57:04 +00:00
|
|
|
void Free_Chunk(struct chunk *);
|
2002-11-11 18:55:57 +00:00
|
|
|
struct chunk *Clone_Chunk(const struct chunk *);
|
2004-03-16 17:07:06 +00:00
|
|
|
int Add_Chunk(struct disk *, daddr_t, daddr_t, const char *, chunk_e, int,
|
|
|
|
u_long, const char *);
|
2002-11-11 18:55:57 +00:00
|
|
|
void *read_block(int, daddr_t, u_long);
|
2002-10-22 09:13:02 +00:00
|
|
|
int write_block(int, daddr_t, const void *, u_long);
|
2002-11-11 18:55:57 +00:00
|
|
|
struct disklabel *read_disklabel(int, daddr_t, u_long);
|
2003-11-02 08:39:08 +00:00
|
|
|
struct disk *Int_Open_Disk(const char *, char *);
|
2001-05-13 20:08:54 +00:00
|
|
|
int Fixup_Names(struct disk *);
|
2002-11-11 18:55:57 +00:00
|
|
|
int MakeDevChunk(const struct chunk *, const char *);
|
1996-03-24 18:55:39 +00:00
|
|
|
__END_DECLS
|
1995-04-28 23:57:04 +00:00
|
|
|
|
|
|
|
#define dprintf printf
|
1995-04-29 04:50:39 +00:00
|
|
|
|
|
|
|
/* TODO
|
|
|
|
*
|
2003-01-01 18:49:04 +00:00
|
|
|
* Need an error string mechanism from the functions instead of warn()
|
1995-05-30 08:29:07 +00:00
|
|
|
*
|
1995-04-29 04:50:39 +00:00
|
|
|
* Make sure only FreeBSD start at offset==0
|
1995-05-30 08:29:07 +00:00
|
|
|
*
|
1995-04-29 04:50:39 +00:00
|
|
|
* Collapse must align.
|
1995-05-30 08:29:07 +00:00
|
|
|
*
|
1995-04-29 04:50:39 +00:00
|
|
|
* Make Write_Disk(struct disk*)
|
1995-05-30 08:29:07 +00:00
|
|
|
*
|
1995-04-29 04:50:39 +00:00
|
|
|
* Consider booting from OnTrack'ed disks.
|
|
|
|
*
|
|
|
|
* Get Bios-geom, ST506 & OnTrack from driver (or otherwise)
|
|
|
|
*
|
|
|
|
* Make Create_DWIM().
|
|
|
|
*
|
1995-04-29 07:21:14 +00:00
|
|
|
* Make Is_Unchanged(struct disk *d1, struct chunk *c1)
|
1995-05-30 08:29:07 +00:00
|
|
|
*
|
1995-05-04 07:00:57 +00:00
|
|
|
* don't rename slices unless we have to
|
1995-04-29 04:50:39 +00:00
|
|
|
*
|
|
|
|
*Sample output from tst01:
|
|
|
|
*
|
1996-11-27 22:44:43 +00:00
|
|
|
* Debug_Disk(wd0) flags=0 bios_geom=0/0/0
|
1995-04-29 04:50:39 +00:00
|
|
|
* >> 0x3d040 0 1411200 1411199 wd0 0 whole 0 0
|
|
|
|
* >>>> 0x3d080 0 960120 960119 wd0s1 3 freebsd 0 8
|
|
|
|
* >>>>>> 0x3d100 0 40960 40959 wd0s1a 5 part 0 0
|
|
|
|
* >>>>>> 0x3d180 40960 131072 172031 wd0s1b 5 part 0 0
|
|
|
|
* >>>>>> 0x3d1c0 172032 409600 581631 wd0s1e 5 part 0 0
|
|
|
|
* >>>>>> 0x3d200 581632 378488 960119 wd0s1f 5 part 0 0
|
|
|
|
* >>>> 0x3d140 960120 5670 965789 wd0s2 4 extended 0 8
|
1995-05-06 03:28:32 +00:00
|
|
|
* >>>>>> 0x3d2c0 960120 63 960182 - 6 unused 0 0
|
1995-04-29 04:50:39 +00:00
|
|
|
* >>>>>> 0x3d0c0 960183 5607 965789 wd0s5 2 fat 0 8
|
|
|
|
* >>>> 0x3d280 965790 1890 967679 wd0s3 1 foo -2 8
|
|
|
|
* >>>> 0x3d300 967680 443520 1411199 wd0s4 3 freebsd 0 8
|
|
|
|
* >>>>>> 0x3d340 967680 443520 1411199 wd0s4a 5 part 0 0
|
|
|
|
*
|
|
|
|
* ^ ^ ^ ^ ^ ^ ^ ^ ^ ^
|
|
|
|
* level chunkptr start size end name type subtype flags
|
|
|
|
*
|
|
|
|
* Underlying data structure:
|
|
|
|
*
|
|
|
|
* Legend:
|
|
|
|
* <struct chunk> --> part
|
|
|
|
* |
|
|
|
|
* v next
|
|
|
|
*
|
|
|
|
* <wd0> --> <wd0s1> --> <wd0s1a>
|
|
|
|
* | |
|
|
|
|
* | v
|
|
|
|
* | <wd0s1b>
|
|
|
|
* | |
|
|
|
|
* | v
|
|
|
|
* | <wd0s1e>
|
|
|
|
* | |
|
|
|
|
* | v
|
|
|
|
* | <wd0s1f>
|
|
|
|
* |
|
|
|
|
* v
|
1995-05-06 03:28:32 +00:00
|
|
|
* <wd0s2> --> <unused>
|
1995-04-29 04:50:39 +00:00
|
|
|
* | |
|
|
|
|
* | v
|
|
|
|
* | <wd0s5>
|
|
|
|
* |
|
|
|
|
* v
|
1995-05-30 08:29:07 +00:00
|
|
|
* <wd0s3>
|
1995-04-29 04:50:39 +00:00
|
|
|
* |
|
|
|
|
* v
|
|
|
|
* <wd0s4> --> <wd0s4a>
|
|
|
|
*
|
|
|
|
*
|
|
|
|
*/
|