Subversion Repositories HelenOS

Rev

Rev 3511 | Rev 3523 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 3511 Rev 3520
Line 32... Line 32...
32
 
32
 
33
import sys
33
import sys
34
import os
34
import os
35
import random
35
import random
36
import xstruct
36
import xstruct
-
 
37
import array
37
 
38
 
38
def align_up(size, alignment):
39
def align_up(size, alignment):
39
    "Return size aligned up to alignment"
40
    "Return size aligned up to alignment"
40
   
41
   
41
    if (size % alignment == 0):
42
    if (size % alignment == 0):
42
        return size
43
        return size
43
   
44
   
44
    return (((size / alignment) + 1) * alignment)
45
    return (((size / alignment) + 1) * alignment)
45
 
46
 
46
def subtree_size(root, cluster_size):
47
def subtree_size(root, cluster_size, dirent_size):
47
    "Recursive directory walk and calculate size"
48
    "Recursive directory walk and calculate size"
48
   
49
   
49
    size = 0
50
    size = 0
50
    files = 0
51
    files = 0
51
   
52
   
Line 55... Line 56...
55
        if (os.path.isfile(canon)):
56
        if (os.path.isfile(canon)):
56
            size += align_up(os.path.getsize(canon), cluster_size)
57
            size += align_up(os.path.getsize(canon), cluster_size)
57
            files += 1
58
            files += 1
58
       
59
       
59
        if (os.path.isdir(canon)):
60
        if (os.path.isdir(canon)):
60
            size += subtree_size(canon, cluster_size)
61
            size += subtree_size(canon, cluster_size, dirent_size)
61
            files += 1
62
            files += 1
62
   
63
   
63
    return size + align_up(files * 32, cluster_size)
64
    return size + align_up(files * dirent_size, cluster_size)
64
 
65
 
65
def root_entries(root):
66
def root_entries(root):
66
    "Return number of root directory entries"
67
    "Return number of root directory entries"
67
   
68
   
68
    return len(os.listdir(root))
69
    return len(os.listdir(root))
69
 
70
 
-
 
71
def write_file(path, outf, cluster_size, data_start, fat):
-
 
72
    "Store the contents of a file"
-
 
73
   
-
 
74
    size = os.path.getsize(path)
-
 
75
    prev = -1
-
 
76
    first = -1
-
 
77
   
-
 
78
    inf = file(path, "r")
-
 
79
    rd = 0;
-
 
80
    while (rd < size):
-
 
81
        data = inf.read(cluster_size);
-
 
82
       
-
 
83
        empty_cluster = fat.index(0)
-
 
84
       
-
 
85
        fat[empty_cluster] = 0xffff
-
 
86
        if (prev != -1):
-
 
87
            fat[prev] = empty_cluster
-
 
88
        else:
-
 
89
            first = empty_cluster
-
 
90
       
-
 
91
        prev = empty_cluster
-
 
92
       
-
 
93
        outf.seek(data_start + empty_cluster * cluster_size)
-
 
94
        outf.write(data)
-
 
95
        rd += len(data)
-
 
96
    inf.close()
-
 
97
   
-
 
98
    return first, size
-
 
99
 
-
 
100
DIR_ENTRY = """little:
-
 
101
    char name[8]               /* file name */
-
 
102
    char ext[3]                /* file extension */
-
 
103
    uint8_t attr               /* file attributes */
-
 
104
    padding[1]                 /* reserved for NT */
-
 
105
    uint8_t ctime_fine         /* create time (fine resolution) */
-
 
106
    uint16_t ctime             /* create time */
-
 
107
    uint16_t cdate             /* create date */
-
 
108
    uint16_t adate             /* access date */
-
 
109
    padding[2]                 /* EA-index */
-
 
110
    uint16_t mtime             /* modification time */
-
 
111
    uint16_t mdate             /* modification date */
-
 
112
    uint16_t cluster           /* first cluster */
-
 
113
    uint32_t size              /* file size */
-
 
114
"""
-
 
115
 
-
 
116
def mangle_fname(name):
-
 
117
    # FIXME: filter illegal characters
-
 
118
    fname = (name.split('.')[0] + '          ').upper()[0:8]
-
 
119
    return fname
-
 
120
 
-
 
121
def mangle_ext(name):
-
 
122
    # FIXME: filter illegal characters
-
 
123
    ext = (name.split('.')[1] + '  ').upper()[0:3]
-
 
124
    return ext
-
 
125
 
-
 
126
def create_dirent(name, directory, cluster, size):
-
 
127
    dir_entry = xstruct.create(DIR_ENTRY)
-
 
128
   
-
 
129
    dir_entry.name = mangle_fname(name)
-
 
130
    dir_entry.ext = mangle_ext(name)
-
 
131
   
-
 
132
    if (directory):
-
 
133
        dir_entry.attr = 0x30
-
 
134
    else:
-
 
135
        dir_entry.attr = 0x20
-
 
136
   
-
 
137
    dir_entry.ctime_fine = 0 # FIXME
-
 
138
    dir_entry.ctime = 0 # FIXME
-
 
139
    dir_entry.cdate = 0 # FIXME
-
 
140
    dir_entry.adate = 0 # FIXME
-
 
141
    dir_entry.mtime = 0 # FIXME
-
 
142
    dir_entry.mdate = 0 # FIXME
-
 
143
    dir_entry.cluster = cluster
-
 
144
    dir_entry.size = size
-
 
145
   
-
 
146
    return dir_entry
-
 
147
 
-
 
148
def recursion(head, root, outf, cluster_size, root_start, data_start, fat):
-
 
149
    "Recursive directory walk"
-
 
150
   
-
 
151
    directory = []
-
 
152
    for name in os.listdir(root):
-
 
153
        canon = os.path.join(root, name)
-
 
154
       
-
 
155
        if (os.path.isfile(canon)):
-
 
156
            rv = write_file(canon, outf, cluster_size, data_start, fat)
-
 
157
            directory.append(create_dirent(name, False, rv[0], rv[1]))
-
 
158
   
-
 
159
    if (head):
-
 
160
        outf.seek(root_start)
-
 
161
        for dir_entry in directory:
-
 
162
            outf.write(dir_entry.pack())
-
 
163
 
70
BOOT_SECTOR = """little:
164
BOOT_SECTOR = """little:
71
    uint8_t jmp[3]             /* jump instruction */
165
    uint8_t jmp[3]             /* jump instruction */
72
    char oem[8]                /* OEM string */
166
    char oem[8]                /* OEM string */
73
    uint16_t sector            /* bytes per sector */
167
    uint16_t sector            /* bytes per sector */
74
    uint8_t cluster            /* sectors per cluster */
168
    uint8_t cluster            /* sectors per cluster */
Line 93... Line 187...
93
    padding[448]               /* boot code */
187
    padding[448]               /* boot code */
94
    uint8_t boot_signature[2]  /* boot signature */
188
    uint8_t boot_signature[2]  /* boot signature */
95
"""
189
"""
96
 
190
 
97
EMPTY_SECTOR = """little:
191
EMPTY_SECTOR = """little:
98
    padding[512]
192
    padding[512]               /* empty sector data */
-
 
193
"""
-
 
194
 
-
 
195
FAT_ENTRY = """little:
-
 
196
    uint16_t next              /* FAT16 entry */
99
"""
197
"""
100
 
198
 
101
def usage(prname):
199
def usage(prname):
102
    "Print usage syntax"
200
    "Print usage syntax"
103
    print prname + " <PATH> <IMAGE>"
201
    print prname + " <PATH> <IMAGE>"
Line 110... Line 208...
110
    path = os.path.abspath(sys.argv[1])
208
    path = os.path.abspath(sys.argv[1])
111
    if (not os.path.isdir(path)):
209
    if (not os.path.isdir(path)):
112
        print "<PATH> must be a directory"
210
        print "<PATH> must be a directory"
113
        return
211
        return
114
   
212
   
-
 
213
    fat16_clusters = 4096
-
 
214
   
115
    sector_size = 512
215
    sector_size = 512
116
    cluster_size = 4096
216
    cluster_size = 4096
-
 
217
    dirent_size = 32
-
 
218
    fatent_size = 2
-
 
219
    fat_count = 2
-
 
220
    reserved_clusters = 2
117
   
221
   
-
 
222
    # Make sure the filesystem is large enought for FAT16
-
 
223
    size = subtree_size(path, cluster_size, dirent_size) + reserved_clusters * cluster_size
-
 
224
    while (size / cluster_size < fat16_clusters):
-
 
225
        if (cluster_size > sector_size):
-
 
226
            cluster_size /= 2
-
 
227
            size = subtree_size(path, cluster_size, dirent_size) + reserved_clusters * cluster_size
-
 
228
        else:
118
    root_size = align_up(root_entries(sys.argv[1]) * 32, sector_size)
229
            size = fat16_clusters * cluster_size + reserved_clusters * cluster_size
-
 
230
   
119
    size = subtree_size(sys.argv[1], cluster_size)
231
    root_size = align_up(root_entries(path) * dirent_size, cluster_size)
-
 
232
   
120
    fat_size = align_up(size / cluster_size * 2, sector_size)
233
    fat_size = align_up(align_up(size, cluster_size) / cluster_size * fatent_size, sector_size)
121
   
234
   
122
    sectors = (cluster_size + 2 * fat_size + root_size + size) / sector_size
235
    sectors = (cluster_size + fat_count * fat_size + root_size + size) / sector_size
-
 
236
    root_start = cluster_size + fat_count * fat_size
-
 
237
    data_start = root_start + root_size
123
   
238
   
124
    outf = file(sys.argv[2], "w")
239
    outf = file(sys.argv[2], "w")
125
   
240
   
126
    boot_sector = xstruct.create(BOOT_SECTOR)
241
    boot_sector = xstruct.create(BOOT_SECTOR)
127
    boot_sector.jmp = [0xEB, 0x3C, 0x90]
242
    boot_sector.jmp = [0xEB, 0x3C, 0x90]
128
    boot_sector.oem = "MSDOS5.0"
243
    boot_sector.oem = "MSDOS5.0"
129
    boot_sector.sector = sector_size
244
    boot_sector.sector = sector_size
130
    boot_sector.cluster = cluster_size / sector_size
245
    boot_sector.cluster = cluster_size / sector_size
131
    boot_sector.reserved = cluster_size / sector_size
246
    boot_sector.reserved = cluster_size / sector_size
132
    boot_sector.fats = 2
247
    boot_sector.fats = fat_count
133
    boot_sector.rootdir = root_size / 32
248
    boot_sector.rootdir = root_size / dirent_size
134
    boot_sector.sectors = (sectors if (sectors <= 65535) else 0)
249
    boot_sector.sectors = (sectors if (sectors <= 65535) else 0)
135
    boot_sector.descriptor = 0xF8
250
    boot_sector.descriptor = 0xF8
136
    boot_sector.fat_sectors = fat_size / sector_size
251
    boot_sector.fat_sectors = fat_size / sector_size
137
    boot_sector.track_sectors = 63
252
    boot_sector.track_sectors = 63
138
    boot_sector.heads = 6
253
    boot_sector.heads = 6
Line 148... Line 263...
148
   
263
   
149
    outf.write(boot_sector.pack())
264
    outf.write(boot_sector.pack())
150
   
265
   
151
    empty_sector = xstruct.create(EMPTY_SECTOR)
266
    empty_sector = xstruct.create(EMPTY_SECTOR)
152
   
267
   
153
    # Reserved sectors (boot_sector.reserved - boot_sector)
268
    # Reserved sectors
154
    for i in range(1, boot_sector.reserved):
269
    for i in range(1, cluster_size / sector_size):
155
        outf.write(empty_sector.pack())
270
        outf.write(empty_sector.pack())
156
   
271
   
157
    # FAT tables
272
    # FAT tables
158
    for i in range(0, boot_sector.fats):
273
    for i in range(0, fat_count):
159
        for j in range(0, boot_sector.fat_sectors):
274
        for j in range(0, boot_sector.fat_sectors):
160
            outf.write(empty_sector.pack())
275
            outf.write(empty_sector.pack())
161
   
276
   
162
    # Root directory
277
    # Root directory
163
    for i in range(0, root_size / sector_size):
278
    for i in range(0, root_size / sector_size):
Line 165... Line 280...
165
   
280
   
166
    # Data
281
    # Data
167
    for i in range(0, size / sector_size):
282
    for i in range(0, size / sector_size):
168
        outf.write(empty_sector.pack())
283
        outf.write(empty_sector.pack())
169
   
284
   
-
 
285
    fat = array.array('L', [0] * (fat_size / fatent_size))
-
 
286
    fat[0] = 0xfff8
-
 
287
    fat[1] = 0xffff
-
 
288
   
-
 
289
    recursion(True, path, outf, cluster_size, root_start, data_start, fat)
-
 
290
   
-
 
291
    # Store FAT
-
 
292
    fat_entry = xstruct.create(FAT_ENTRY)
-
 
293
    for i in range(0, fat_count):
-
 
294
        outf.seek(cluster_size + i * fat_size)
-
 
295
        for j in range(0, fat_size / fatent_size):
-
 
296
            fat_entry.next = fat[j]
-
 
297
            outf.write(fat_entry.pack())
-
 
298
   
170
    outf.close()
299
    outf.close()
171
   
300
   
172
if __name__ == '__main__':
301
if __name__ == '__main__':
173
    main()
302
    main()