Subversion Repositories HelenOS

Rev

Rev 3264 | Rev 3511 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
3264 decky 1
#!/usr/bin/env python
2
#
3
# Copyright (c) 2008 Martin Decky
4
# All rights reserved.
5
#
6
# Redistribution and use in source and binary forms, with or without
7
# modification, are permitted provided that the following conditions
8
# are met:
9
#
10
# - Redistributions of source code must retain the above copyright
11
#   notice, this list of conditions and the following disclaimer.
12
# - Redistributions in binary form must reproduce the above copyright
13
#   notice, this list of conditions and the following disclaimer in the
14
#   documentation and/or other materials provided with the distribution.
15
# - The name of the author may not be used to endorse or promote products
16
#   derived from this software without specific prior written permission.
17
#
18
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
#
29
"""
30
FAT creator
31
"""
32
 
33
import sys
34
import os
35
import random
36
import xstruct
37
 
3509 decky 38
def align_up(size, alignment):
39
	"Return size aligned up to alignment"
40
 
41
	if (size % alignment == 0):
42
		return size
43
 
44
	return (((size / alignment) + 1) * alignment)
45
 
46
def subtree_size(root, cluster_size):
47
	"Recursive directory walk and calculate size"
48
 
49
	size = 0
50
	files = 0
51
 
52
	for name in os.listdir(root):
53
		canon = os.path.join(root, name)
54
 
55
		if (os.path.isfile(canon)):
56
			size += align_up(os.path.getsize(canon), cluster_size)
57
			files += 1
58
 
59
		if (os.path.isdir(canon)):
60
			size += subtree_size(canon, cluster_size)
61
			files += 1
62
 
63
	return size + align_up(files * 32, cluster_size)
64
 
65
def root_entries(root):
66
	"Return number of root directory entries"
67
 
68
	return len(os.listdir(root))
69
 
3264 decky 70
BOOT_SECTOR = """little:
71
	uint8_t jmp[3]             /* jump instruction */
72
	char oem[8]                /* OEM string */
73
	uint16_t sector            /* bytes per sector */
74
	uint8_t cluster            /* sectors per cluster */
75
	uint16_t reserved          /* reserved sectors */
76
	uint8_t fats               /* number of FATs */
77
	uint16_t rootdir           /* root directory entries */
78
	uint16_t sectors           /* total number of sectors */
79
	uint8_t descriptor         /* media descriptor */
80
	uint16_t fat_sectors       /* sectors per single FAT */
81
	uint16_t track_sectors     /* sectors per track */
82
	uint16_t heads             /* number of heads */
83
	uint32_t hidden            /* hidden sectors */
84
	uint32_t sectors_big       /* total number of sectors (if sectors == 0) */
85
 
86
	/* Extended BIOS Parameter Block */
87
	uint8_t drive              /* physical drive number */
88
	padding[1]                 /* reserved (current head) */
89
	uint8_t extboot_signature  /* extended boot signature */
90
	uint32_t serial            /* serial number */
91
	char label[11]             /* volume label */
92
	char fstype[8]             /* filesystem type */
93
	padding[448]               /* boot code */
94
	uint8_t boot_signature[2]  /* boot signature */
95
"""
96
 
97
def usage(prname):
98
	"Print usage syntax"
99
	print prname + " <PATH> <IMAGE>"
100
 
101
def main():
102
	if (len(sys.argv) < 3):
103
		usage(sys.argv[0])
104
		return
105
 
106
	path = os.path.abspath(sys.argv[1])
107
	if (not os.path.isdir(path)):
108
		print "<PATH> must be a directory"
109
		return
110
 
3509 decky 111
	sector_size = 512
112
	cluster_size = 4096
113
 
114
	root_size = align_up(root_entries(sys.argv[1]) * 32, sector_size)
115
	size = subtree_size(sys.argv[1], cluster_size)
116
	fat_size = align_up(size / cluster_size * 2, sector_size)
117
 
118
	sectors = (cluster_size + 2 * fat_size + root_size + size) / sector_size
119
 
3264 decky 120
	outf = file(sys.argv[2], "w")
121
 
122
	boot_sector = xstruct.create(BOOT_SECTOR)
123
	boot_sector.jmp = [0xEB, 0x3C, 0x90]
124
	boot_sector.oem = "MSDOS5.0"
3509 decky 125
	boot_sector.sector = sector_size
126
	boot_sector.cluster = cluster_size / sector_size
127
	boot_sector.reserved = cluster_size / sector_size
3264 decky 128
	boot_sector.fats = 2
3509 decky 129
	boot_sector.rootdir = root_size / 32
130
	boot_sector.sectors = (sectors if (sectors <= 65535) else 0)
3264 decky 131
	boot_sector.descriptor = 0xF8
3509 decky 132
	boot_sector.fat_sectors = fat_size / sector_size
133
	boot_sector.track_sectors = 63
134
	boot_sector.heads = 6
3264 decky 135
	boot_sector.hidden = 0
3509 decky 136
	boot_sector.sectors_big = (sectors if (sectors > 65535) else 0)
3264 decky 137
 
3509 decky 138
	boot_sector.drive = 0x80
3264 decky 139
	boot_sector.extboot_signature = 0x29
140
	boot_sector.serial = random.randint(0, 0xFFFFFFFF)
141
	boot_sector.label = "HELENOS"
142
	boot_sector.fstype = "FAT16   "
143
	boot_sector.boot_signature = [0x55, 0xAA]
144
 
145
	outf.write(boot_sector.pack())
146
 
147
	outf.close()
148
 
149
if __name__ == '__main__':
150
	main()