Changeset a35b458 in mainline for tools/mkfat.py
- Timestamp:
- 2018-03-02T20:10:49Z (7 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- f1380b7
- Parents:
- 3061bc1
- git-author:
- Jiří Zárevúcky <zarevucky.jiri@…> (2018-02-28 17:38:31)
- git-committer:
- Jiří Zárevúcky <zarevucky.jiri@…> (2018-03-02 20:10:49)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
tools/mkfat.py
r3061bc1 ra35b458 41 41 def subtree_size(root, cluster_size, dirent_size): 42 42 "Recursive directory walk and calculate size" 43 43 44 44 size = 0 45 45 files = 2 46 46 47 47 for item in listdir_items(root): 48 48 if item.is_file: … … 52 52 size += subtree_size(item.path, cluster_size, dirent_size) 53 53 files += 1 54 54 55 55 return size + align_up(files * dirent_size, cluster_size) 56 56 57 57 def root_entries(root): 58 58 "Return number of root directory entries" 59 59 60 60 return len(os.listdir(root)) 61 61 62 62 def write_file(item, outf, cluster_size, data_start, fat, reserved_clusters): 63 63 "Store the contents of a file" 64 64 65 65 prev = -1 66 66 first = 0 67 67 68 68 for data in chunks(item, cluster_size): 69 69 empty_cluster = fat.index(0) 70 70 fat[empty_cluster] = 0xffff 71 71 72 72 if (prev != -1): 73 73 fat[prev] = empty_cluster 74 74 else: 75 75 first = empty_cluster 76 76 77 77 prev = empty_cluster 78 78 79 79 outf.seek(data_start + (empty_cluster - reserved_clusters) * cluster_size) 80 80 outf.write(data) 81 81 82 82 return first, item.size 83 83 84 84 def write_directory(directory, outf, cluster_size, data_start, fat, reserved_clusters, dirent_size, empty_cluster): 85 85 "Store the contents of a directory" 86 86 87 87 length = len(directory) 88 88 size = length * dirent_size 89 89 prev = -1 90 90 first = 0 91 91 92 92 i = 0 93 93 rd = 0; … … 99 99 else: 100 100 first = empty_cluster 101 101 102 102 prev = empty_cluster 103 103 104 104 data = bytes() 105 105 data_len = 0 … … 107 107 if (i == 0): 108 108 directory[i].cluster = empty_cluster 109 109 110 110 data += directory[i].pack() 111 111 data_len += dirent_size 112 112 i += 1 113 113 114 114 outf.seek(data_start + (empty_cluster - reserved_clusters) * cluster_size) 115 115 outf.write(data) 116 116 rd += len(data) 117 117 118 118 return first, size 119 119 … … 188 188 def fat_lchars(name): 189 189 "Filter FAT legal characters" 190 190 191 191 filtered_name = b'' 192 192 filtered = False 193 193 194 194 for char in name.encode('ascii', 'replace').upper(): 195 195 if char in lchars: … … 198 198 filtered_name += b'_' 199 199 filtered = True 200 200 201 201 return (filtered_name, filtered) 202 202 203 203 def fat_name83(name, name83_list): 204 204 "Create a 8.3 name for the given name" 205 205 206 206 ascii_name, lfn = fat_lchars(name) 207 207 # Splitting works only on strings, not on bytes 208 208 ascii_parts = ascii_name.decode('utf8').split('.') 209 209 210 210 short_name = '' 211 211 short_ext = '' 212 212 213 213 if len(ascii_name) > 11: 214 214 lfn = True 215 215 216 216 if len(ascii_parts) > 0: 217 217 short_name = ascii_parts[0] 218 218 if len(short_name) > 8: 219 219 lfn = True 220 220 221 221 if len(ascii_parts) > 1: 222 222 short_ext = ascii_parts[-1] 223 223 if len(short_ext) > 3: 224 224 lfn = True 225 225 226 226 if len(ascii_parts) > 2: 227 227 lfn = True 228 228 229 229 if lfn == False: 230 230 name83_list.append(short_name + '.' + short_ext) 231 231 return (short_name.ljust(8)[0:8], short_ext.ljust(3)[0:3], False) 232 232 233 233 # For filenames with multiple extensions, we treat the last one 234 234 # as the actual extension. The rest of the filename is stripped … … 236 236 for part in ascii_parts[1:-1]: 237 237 short_name += part 238 238 239 239 for number in range(1, 999999): 240 240 number_str = ('~' + str(number)).upper() 241 241 242 242 if len(short_name) + len(number_str) > 8: 243 243 short_name = short_name[0:8 - len(number_str)] 244 244 245 245 short_name += number_str; 246 246 247 247 if not (short_name + '.' + short_ext) in name83_list: 248 248 break 249 249 250 250 name83_list.append(short_name + '.' + short_ext) 251 251 return (short_name.ljust(8)[0:8], short_ext.ljust(3)[0:3], True) … … 253 253 def create_lfn_dirent(name, seq, checksum): 254 254 "Create LFN directory entry" 255 255 256 256 entry = xstruct.create(LFN_DIR_ENTRY) 257 257 name_rest = name[26:] 258 258 259 259 if len(name_rest) > 0: 260 260 entry.seq = seq 261 261 else: 262 262 entry.seq = seq | 0x40 263 263 264 264 entry.name1 = name[0:10] 265 265 entry.name2 = name[10:22] 266 266 entry.name3 = name[22:26] 267 267 268 268 entry.attr = 0x0F 269 269 entry.rec_type = 0 270 270 entry.checksum = checksum 271 271 entry.cluster = 0 272 272 273 273 return (entry, name_rest) 274 274 275 275 def lfn_checksum(name): 276 276 "Calculate LFN checksum" 277 277 278 278 checksum = 0 279 279 for i in range(0, 11): 280 280 checksum = (((checksum & 1) << 7) + (checksum >> 1) + ord(name[i])) & 0xFF 281 281 282 282 return checksum 283 283 284 284 def create_dirent(name, name83_list, directory, cluster, size): 285 285 short_name, short_ext, lfn = fat_name83(name, name83_list) 286 286 287 287 dir_entry = xstruct.create(DIR_ENTRY) 288 288 289 289 dir_entry.name = short_name 290 290 dir_entry.ext = short_ext 291 291 292 292 if (directory): 293 293 dir_entry.attr = 0x30 294 294 else: 295 295 dir_entry.attr = 0x20 296 296 297 297 dir_entry.lcase = 0x18 298 298 dir_entry.ctime_fine = 0 # FIXME … … 303 303 dir_entry.mdate = 0 # FIXME 304 304 dir_entry.cluster = cluster 305 305 306 306 if (directory): 307 307 dir_entry.size = 0 308 308 else: 309 309 dir_entry.size = size 310 310 311 311 if not lfn: 312 312 return [dir_entry] 313 313 314 314 long_name = name.encode('utf_16_le') 315 315 entries = [dir_entry] 316 316 317 317 seq = 1 318 318 checksum = lfn_checksum(dir_entry.name + dir_entry.ext) 319 319 320 320 while len(long_name) > 0: 321 321 long_entry, long_name = create_lfn_dirent(long_name, seq, checksum) 322 322 entries.append(long_entry) 323 323 seq += 1 324 324 325 325 entries.reverse() 326 326 return entries … … 328 328 def create_dot_dirent(empty_cluster): 329 329 dir_entry = xstruct.create(DOT_DIR_ENTRY) 330 330 331 331 dir_entry.signature = 0x2e 332 332 dir_entry.name = b' ' 333 333 dir_entry.ext = b' ' 334 334 dir_entry.attr = 0x10 335 335 336 336 dir_entry.ctime_fine = 0 # FIXME 337 337 dir_entry.ctime = 0 # FIXME … … 342 342 dir_entry.cluster = empty_cluster 343 343 dir_entry.size = 0 344 344 345 345 return dir_entry 346 346 347 347 def create_dotdot_dirent(parent_cluster): 348 348 dir_entry = xstruct.create(DOTDOT_DIR_ENTRY) 349 349 350 350 dir_entry.signature = [0x2e, 0x2e] 351 351 dir_entry.name = b' ' 352 352 dir_entry.ext = b' ' 353 353 dir_entry.attr = 0x10 354 354 355 355 dir_entry.ctime_fine = 0 # FIXME 356 356 dir_entry.ctime = 0 # FIXME … … 361 361 dir_entry.cluster = parent_cluster 362 362 dir_entry.size = 0 363 363 364 364 return dir_entry 365 365 366 366 def recursion(head, root, outf, cluster_size, root_start, data_start, fat, reserved_clusters, dirent_size, parent_cluster): 367 367 "Recursive directory walk" 368 368 369 369 directory = [] 370 370 name83_list = [] 371 371 372 372 if not head: 373 373 # Directory cluster preallocation 374 374 empty_cluster = fat.index(0) 375 375 fat[empty_cluster] = 0xFFFF 376 376 377 377 directory.append(create_dot_dirent(empty_cluster)) 378 378 directory.append(create_dotdot_dirent(parent_cluster)) 379 379 else: 380 380 empty_cluster = 0 381 381 382 382 for item in listdir_items(root): 383 383 if item.is_file: … … 387 387 rv = recursion(False, item.path, outf, cluster_size, root_start, data_start, fat, reserved_clusters, dirent_size, empty_cluster) 388 388 directory.extend(create_dirent(item.name, name83_list, True, rv[0], rv[1])) 389 389 390 390 if head: 391 391 outf.seek(root_start) … … 410 410 uint32_t hidden /* hidden sectors */ 411 411 uint32_t sectors_big /* total number of sectors (if sectors == 0) */ 412 412 413 413 /* Extended BIOS Parameter Block */ 414 414 uint8_t drive /* physical drive number */ … … 438 438 usage(sys.argv[0]) 439 439 return 440 440 441 441 if (not sys.argv[1].isdigit()): 442 442 print("<EXTRA_BYTES> must be a number") 443 443 return 444 444 445 445 extra_bytes = int(sys.argv[1]) 446 446 447 447 path = os.path.abspath(sys.argv[2]) 448 448 if (not os.path.isdir(path)): 449 449 print("<PATH> must be a directory") 450 450 return 451 451 452 452 fat16_clusters = 4096 453 453 454 454 sector_size = 512 455 455 cluster_size = 4096 … … 458 458 fat_count = 2 459 459 reserved_clusters = 2 460 460 461 461 # Make sure the filesystem is large enough for FAT16 462 462 size = subtree_size(path, cluster_size, dirent_size) + reserved_clusters * cluster_size + extra_bytes … … 467 467 else: 468 468 size = fat16_clusters * cluster_size + reserved_clusters * cluster_size 469 469 470 470 root_size = align_up(root_entries(path) * dirent_size, cluster_size) 471 471 472 472 fat_size = align_up(align_up(size, cluster_size) // cluster_size * fatent_size, sector_size) 473 473 474 474 sectors = (cluster_size + fat_count * fat_size + root_size + size) // sector_size 475 475 root_start = cluster_size + fat_count * fat_size 476 476 data_start = root_start + root_size 477 477 478 478 outf = open(sys.argv[3], "wb") 479 479 480 480 boot_sector = xstruct.create(BOOT_SECTOR) 481 481 boot_sector.jmp = [0xEB, 0x3C, 0x90] … … 499 499 else: 500 500 boot_sector.sectors_big = 0 501 501 502 502 boot_sector.drive = 0x80 503 503 boot_sector.extboot_signature = 0x29 … … 506 506 boot_sector.fstype = b'FAT16 ' 507 507 boot_sector.boot_signature = [0x55, 0xAA] 508 508 509 509 outf.write(boot_sector.pack()) 510 510 511 511 empty_sector = xstruct.create(EMPTY_SECTOR) 512 512 513 513 # Reserved sectors 514 514 for i in range(1, cluster_size // sector_size): 515 515 outf.write(empty_sector.pack()) 516 516 517 517 # FAT tables 518 518 for i in range(0, fat_count): 519 519 for j in range(0, fat_size // sector_size): 520 520 outf.write(empty_sector.pack()) 521 521 522 522 # Root directory 523 523 for i in range(0, root_size // sector_size): 524 524 outf.write(empty_sector.pack()) 525 525 526 526 # Data 527 527 for i in range(0, size // sector_size): 528 528 outf.write(empty_sector.pack()) 529 529 530 530 fat = array.array('L', [0] * (fat_size // fatent_size)) 531 531 fat[0] = 0xfff8 532 532 fat[1] = 0xffff 533 533 534 534 recursion(True, path, outf, cluster_size, root_start, data_start, fat, reserved_clusters, dirent_size, 0) 535 535 536 536 # Store FAT 537 537 fat_entry = xstruct.create(FAT_ENTRY) … … 541 541 fat_entry.next = fat[j] 542 542 outf.write(fat_entry.pack()) 543 543 544 544 outf.close() 545 545
Note:
See TracChangeset
for help on using the changeset viewer.