5 * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation; either version 2 of the
10 * License, or (at your option) any later version.
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
26 * Virtual disk emulation
32 /** Number of cylinders */
33 #define VDISK_CYLINDERS 1024 /* Maximum possible */
35 /** Number of heads */
36 #define VDISK_HEADS 255
38 /** Number of sectors per track */
39 #define VDISK_SECTORS_PER_TRACK 63
41 /** Sector size (in bytes) */
42 #define VDISK_SECTOR_SIZE 512
44 /** Partition start LBA */
45 #define VDISK_PARTITION_LBA 128
47 /** Cluster size (in sectors) */
48 #define VDISK_CLUSTER_COUNT 64
50 /** Cluster size (in bytes) */
51 #define VDISK_CLUSTER_SIZE ( VDISK_CLUSTER_COUNT * VDISK_SECTOR_SIZE )
53 /** Number of clusters */
54 #define VDISK_CLUSTERS 0x03ffc000ULL /* Fill 2TB disk */
56 /** Maximum number of virtual files
58 * The total number of files must be strictly less than the number of
59 * sectors per cluster.
61 #define VDISK_MAX_FILES ( VDISK_CLUSTER_COUNT - 1 )
63 /** Maximum file size (in sectors) */
64 #define VDISK_FILE_COUNT 0x800000UL /* max for 32-bit address space */
66 /** Maximum file size (in clusters) */
67 #define VDISK_FILE_CLUSTERS ( VDISK_FILE_COUNT / VDISK_CLUSTER_COUNT )
69 /** File starting LBA */
70 #define VDISK_FILE_LBA( idx ) ( ( (idx) + 1 ) * VDISK_FILE_COUNT )
72 /** File index from LBA */
73 #define VDISK_FILE_IDX( lba ) ( ( (lba) / VDISK_FILE_COUNT ) - 1 )
75 /** File offset (in bytes) from LBA */
76 #define VDISK_FILE_OFFSET( lba ) \
77 ( ( (lba) % VDISK_FILE_COUNT ) * VDISK_SECTOR_SIZE )
79 /** File index from directory entry LBA */
80 #define VDISK_FILE_DIRENT_IDX( lba ) ( ( (lba) - 1 ) % VDISK_CLUSTER_COUNT )
82 /** Number of sectors allocated for FAT */
83 #define VDISK_SECTORS_PER_FAT \
84 ( ( ( VDISK_CLUSTERS * sizeof ( uint32_t ) + \
85 VDISK_CLUSTER_SIZE - 1 ) / VDISK_CLUSTER_SIZE ) \
86 * VDISK_CLUSTER_COUNT )
88 /** Number of reserved sectors */
89 #define VDISK_RESERVED_COUNT VDISK_CLUSTER_COUNT
91 /** Starting cluster number for file */
92 #define VDISK_FILE_CLUSTER( idx ) \
93 ( ( ( ( VDISK_FILE_COUNT - VDISK_PARTITION_LBA - \
94 VDISK_RESERVED_COUNT - VDISK_SECTORS_PER_FAT ) / \
95 VDISK_CLUSTER_COUNT ) + 2 ) + \
96 ( (idx) * VDISK_FILE_CLUSTERS ) )
98 /** Total number of sectors within partition */
99 #define VDISK_PARTITION_COUNT \
100 ( VDISK_RESERVED_COUNT + VDISK_SECTORS_PER_FAT + \
101 ( VDISK_CLUSTERS * VDISK_CLUSTER_COUNT ) )
103 /** Number of sectors */
104 #define VDISK_COUNT ( VDISK_PARTITION_LBA + VDISK_PARTITION_COUNT )
106 /** Calculate sector from cluster */
107 #define VDISK_CLUSTER_SECTOR( cluster ) \
108 ( ( ( (cluster) - 2 ) * VDISK_CLUSTER_COUNT ) + \
109 VDISK_RESERVED_COUNT + VDISK_SECTORS_PER_FAT )
111 /*****************************************************************************
115 *****************************************************************************
118 /** Master Boot Record LBA */
119 #define VDISK_MBR_LBA 0x00000000
121 /** Master Boot Record sector count */
122 #define VDISK_MBR_COUNT 1
124 /** Partition table entry */
125 struct vdisk_partition
{
128 /** C/H/S start address */
129 uint8_t chs_start
[3];
130 /** System indicator (partition type) */
132 /** C/H/S end address */
134 /** Linear start address */
138 } __attribute__ (( packed
));
140 /** Master Boot Record */
144 /** Disk signature */
148 /** Partition table */
149 struct vdisk_partition partitions
[4];
150 /** 0x55aa signature */
152 } __attribute__ (( packed
));
154 /** MBR boot partition indiciator */
155 #define VDISK_MBR_BOOTABLE 0x80
157 /** MBR type indicator for FAT32 */
158 #define VDISK_MBR_TYPE_FAT32 0x0c
161 #define VDISK_MBR_SIGNATURE 0xc0ffeeee
164 #define VDISK_MBR_MAGIC 0xaa55
166 /*****************************************************************************
170 *****************************************************************************
173 /** Volume Boot Record LBA */
174 #define VDISK_VBR_LBA VDISK_PARTITION_LBA
176 /** Volume Boot Record sector count */
177 #define VDISK_VBR_COUNT 1
179 /** Volume Boot Record */
181 /** Jump instruction */
183 /** OEM identifier */
185 /** Number of bytes per sector */
186 uint16_t bytes_per_sector
;
187 /** Number of sectors per cluster */
188 uint8_t sectors_per_cluster
;
189 /** Number of reserved sectors */
190 uint16_t reserved_sectors
;
191 /** Number of FATs */
193 /** Number of root directory entries (FAT12/FAT16 only) */
194 uint16_t root_directory_entries
;
195 /** Total number of sectors (0 if more than 65535) */
196 uint16_t sectors_short
;
197 /** Media descriptor type */
199 /** Number of sectors per FAT (FAT12/FAT16 only) */
200 uint16_t sectors_per_fat_short
;
201 /** Number of sectors per track */
202 uint16_t sectors_per_track
;
203 /** Number of heads */
205 /** Number of hidden sectors (i.e. LBA of start of partition) */
206 uint32_t hidden_sectors
;
207 /** Total number of sectors */
210 /* FAT32-specific fields */
212 /** Sectors per FAT */
213 uint32_t sectors_per_fat
;
216 /** FAT version number */
218 /** Root directory cluster */
222 /** Backup boot sector */
225 uint8_t reserved
[12];
228 /** Windows NT flags */
232 /** Volume ID serial */
234 /** Label (space-padded) */
236 /** System identifier */
240 /** 0x55aa signature */
242 } __attribute__ (( packed
));
244 /** VBR jump instruction
246 * bootmgr.exe will actually fail unless this is present. Someone
247 * must read specification documents without bothering to understand
248 * what's really happening.
250 #define VDISK_VBR_JUMP_WTF_MS 0xe9
253 #define VDISK_VBR_OEMID "wimboot\0"
255 /** VBR media type */
256 #define VDISK_VBR_MEDIA 0xf8
259 #define VDISK_VBR_SIGNATURE 0x29
261 /** VBR serial number */
262 #define VDISK_VBR_SERIAL 0xf00df00d
265 #define VDISK_VBR_LABEL "wimboot "
267 /** VBR system identifier */
268 #define VDISK_VBR_SYSTEM "FAT32 "
271 #define VDISK_VBR_MAGIC 0xaa55
273 /*****************************************************************************
277 *****************************************************************************
281 #define VDISK_FSINFO_SECTOR 0x00000001
284 #define VDISK_FSINFO_LBA ( VDISK_VBR_LBA + VDISK_FSINFO_SECTOR )
286 /** FSInfo sector count */
287 #define VDISK_FSINFO_COUNT 1
290 struct vdisk_fsinfo
{
291 /** First signature */
294 uint8_t reserved_1
[480];
295 /** Second signature */
297 /** Free cluster count */
299 /** Next free cluster */
302 uint8_t reserved_2
[12];
303 /** Third signature */
305 } __attribute__ (( packed
));
307 /** FSInfo first signature */
308 #define VDISK_FSINFO_MAGIC1 0x41615252
310 /** FSInfo second signature */
311 #define VDISK_FSINFO_MAGIC2 0x61417272
313 /** FSInfo next free cluster */
314 #define VDISK_FSINFO_NEXT_FREE 0xffffffff /* No free clusters */
316 /** FSInfo third signature */
317 #define VDISK_FSINFO_MAGIC3 0xaa550000
319 /*****************************************************************************
321 * Backup Volume Boot Record
323 *****************************************************************************
326 /** Backup Volume Boot Record sector */
327 #define VDISK_BACKUP_VBR_SECTOR 0x00000006
329 /** Backup Volume Boot Record LBA */
330 #define VDISK_BACKUP_VBR_LBA ( VDISK_VBR_LBA + VDISK_BACKUP_VBR_SECTOR )
332 /** Backup Volume Boot Record sector count */
333 #define VDISK_BACKUP_VBR_COUNT 1
335 /*****************************************************************************
337 * File Allocation Table
339 *****************************************************************************
343 #define VDISK_FAT_SECTOR VDISK_RESERVED_COUNT
346 #define VDISK_FAT_LBA ( VDISK_VBR_LBA + VDISK_FAT_SECTOR )
348 /** FAT sector count */
349 #define VDISK_FAT_COUNT VDISK_SECTORS_PER_FAT
351 /** FAT end marker */
352 #define VDISK_FAT_END_MARKER 0x0ffffff8
354 /*****************************************************************************
358 *****************************************************************************
361 /** An 8.3 filename record */
362 struct vdisk_short_filename
{
365 /** Structured 8.3 base name and extension */
371 } __attribute__ (( packed
));
379 /** Creation time in tenths of a second */
380 uint8_t created_deciseconds
;
381 /** Creation time (HMS packed) */
382 uint16_t created_time
;
383 /** Creation date (YMD packed) */
384 uint16_t created_date
;
385 /** Last accessed date (YMD packed) */
386 uint16_t accessed_date
;
387 /** High 16 bits of starting cluster number */
388 uint16_t cluster_high
;
389 /** Modification time (HMS packed) */
390 uint16_t modified_time
;
391 /** Modification date (YMD packed) */
392 uint16_t modified_date
;
393 /** Low 16 bits of starting cluster number */
394 uint16_t cluster_low
;
397 } __attribute__ (( packed
));
399 /** A long filename record */
400 struct vdisk_long_filename
{
401 /** Sequence number */
403 /** Name characters */
409 /** Checksum of 8.3 name */
411 /** Name characters */
415 /** Name characters */
417 } __attribute__ (( packed
));
419 /** Directory entry attributes */
420 enum vdisk_directory_entry_attributes
{
421 VDISK_READ_ONLY
= 0x01,
424 VDISK_VOLUME_LABEL
= 0x08,
425 VDISK_DIRECTORY
= 0x10,
428 /** Long filename end-of-sequence marker */
429 #define VDISK_LFN_END 0x40
431 /** Long filename attributes */
432 #define VDISK_LFN_ATTR \
433 ( VDISK_READ_ONLY | VDISK_HIDDEN | VDISK_SYSTEM | VDISK_VOLUME_LABEL )
435 /** A directory entry */
436 union vdisk_directory_entry
{
437 /** Deleted file marker */
440 struct vdisk_short_filename dos
;
442 struct vdisk_long_filename lfn
;
443 } __attribute__ (( packed
));
445 /** Magic marker for deleted files */
446 #define VDISK_DIRENT_DELETED 0xe5
448 /** Number of directory entries per sector */
449 #define VDISK_DIRENT_PER_SECTOR \
450 ( VDISK_SECTOR_SIZE / \
451 sizeof ( union vdisk_directory_entry ) )
453 /** A directory sector */
454 struct vdisk_directory
{
456 union vdisk_directory_entry entry
[VDISK_DIRENT_PER_SECTOR
];
457 } __attribute__ (( packed
));
459 /*****************************************************************************
463 *****************************************************************************
466 /** Root directory cluster */
467 #define VDISK_ROOT_CLUSTER 2
469 /** Root directory sector */
470 #define VDISK_ROOT_SECTOR VDISK_CLUSTER_SECTOR ( VDISK_ROOT_CLUSTER )
472 /** Root directory LBA */
473 #define VDISK_ROOT_LBA ( VDISK_VBR_LBA + VDISK_ROOT_SECTOR )
475 /*****************************************************************************
479 *****************************************************************************
482 /** Boot directory cluster */
483 #define VDISK_BOOT_CLUSTER 3
485 /** Boot directory sector */
486 #define VDISK_BOOT_SECTOR VDISK_CLUSTER_SECTOR ( VDISK_BOOT_CLUSTER )
488 /** Boot directory LBA */
489 #define VDISK_BOOT_LBA ( VDISK_VBR_LBA + VDISK_BOOT_SECTOR )
491 /*****************************************************************************
495 *****************************************************************************
498 /** Sources directory cluster */
499 #define VDISK_SOURCES_CLUSTER 4
501 /** Sources directory sector */
502 #define VDISK_SOURCES_SECTOR VDISK_CLUSTER_SECTOR ( VDISK_SOURCES_CLUSTER )
504 /** Sources directory LBA */
505 #define VDISK_SOURCES_LBA ( VDISK_VBR_LBA + VDISK_SOURCES_SECTOR )
507 /*****************************************************************************
511 *****************************************************************************
514 /** Fonts directory cluster */
515 #define VDISK_FONTS_CLUSTER 5
517 /** Fonts directory sector */
518 #define VDISK_FONTS_SECTOR VDISK_CLUSTER_SECTOR ( VDISK_FONTS_CLUSTER )
520 /** Fonts directory LBA */
521 #define VDISK_FONTS_LBA ( VDISK_VBR_LBA + VDISK_FONTS_SECTOR )
523 /*****************************************************************************
525 * Resources directory
527 *****************************************************************************
530 /** Resources directory cluster */
531 #define VDISK_RESOURCES_CLUSTER 6
533 /** Resources directory sector */
534 #define VDISK_RESOURCES_SECTOR VDISK_CLUSTER_SECTOR ( VDISK_RESOURCES_CLUSTER )
536 /** Resources directory LBA */
537 #define VDISK_RESOURCES_LBA ( VDISK_VBR_LBA + VDISK_RESOURCES_SECTOR )
539 /*****************************************************************************
543 *****************************************************************************
546 /** EFI directory cluster */
547 #define VDISK_EFI_CLUSTER 7
549 /** EFI directory sector */
550 #define VDISK_EFI_SECTOR VDISK_CLUSTER_SECTOR ( VDISK_EFI_CLUSTER )
552 /** EFI directory LBA */
553 #define VDISK_EFI_LBA ( VDISK_VBR_LBA + VDISK_EFI_SECTOR )
555 /*****************************************************************************
557 * Microsoft directory
559 *****************************************************************************
562 /** Microsoft directory cluster */
563 #define VDISK_MICROSOFT_CLUSTER 8
565 /** Microsoft directory sector */
566 #define VDISK_MICROSOFT_SECTOR VDISK_CLUSTER_SECTOR ( VDISK_MICROSOFT_CLUSTER )
568 /** Microsoft directory LBA */
569 #define VDISK_MICROSOFT_LBA ( VDISK_VBR_LBA + VDISK_MICROSOFT_SECTOR )
571 /*****************************************************************************
575 *****************************************************************************
578 /** Maximum virtual filename length (excluding NUL) */
579 #define VDISK_NAME_LEN 31
581 /** A virtual file */
584 char name
[ VDISK_NAME_LEN
+ 1 /* NUL */ ];
587 /** Length (excluding any zero-padding) */
589 /** Length (including any zero-padding) */
593 * @v file Virtual file
594 * @v data Data buffer
595 * @v offset Starting offset
598 void ( * read
) ( struct vdisk_file
*file
, void *data
, size_t offset
,
600 /** Patch data (optional)
602 * @v file Virtual file
603 * @v data Data buffer
604 * @v offset Starting offset
607 void ( * patch
) ( struct vdisk_file
*file
, void *data
, size_t offset
,
611 extern struct vdisk_file vdisk_files
[VDISK_MAX_FILES
];
613 extern void vdisk_read ( uint64_t lba
, unsigned int count
, void *data
);
614 extern struct vdisk_file
*
615 vdisk_add_file ( const char *name
, void *opaque
, size_t len
,
616 void ( * read
) ( struct vdisk_file
*file
, void *data
,
617 size_t offset
, size_t len
) );
619 vdisk_patch_file ( struct vdisk_file
*file
,
620 void ( * patch
) ( struct vdisk_file
*file
, void *data
,
621 size_t offset
, size_t len
) );
623 #endif /* _VDISK_H */